【问题标题】:Java - Can constants store and calculate other variables within them?Java - 常量可以在其中存储和计算其他变量吗?
【发布时间】:2017-10-17 22:08:53
【问题描述】:

TL;DR 在底部

我目前正在我的社区大学学习编程 1,我刚刚收到关于几周前上交的实验室的反馈。据说,有一个地方我犯了错误,但我不确定是不是错误。

一些背景知识:在我们的实验室中,我们应该编写一个程序来收集和计算用户在几个小时内赚取的总收入,然后扣除必要百分比的所得税、购买商品的钱、债券等。

实验室的部分说明要求我们“将税收、衣服、学校用品、储蓄债券和父母储蓄债券的值定义为‘恒定’(在课堂上此时定义为 final)。”

为了节省空间,我决定继续计算常量本身中每个项目的总值,而不是只将百分比放入常量中并稍后调用它们。

然而,根据我的教授的说法,这个选择是错误的,因为它没有正确声明我的常量。假设,应该存储在常量中的唯一东西是纯数字(即,只是百分比);通过尝试在我的初始化中包含和计算变量,我有效地破坏了我的代码,因为常量将永远将第一个计算锁定到位,并且如果再次运行代码将无法计算新的数字/变量(注意:我刚刚通过一个循环运行程序,看看这是否正确,它仍然可以正常工作。

如果我错了,就这样吧,我最终还是学到了一些东西。但如果不是,我想知道。

这是有问题的代码;你有什么想法?

import javax.swing.JOptionPane;
import java.text.DecimalFormat;

public class Lab2C  
{
    static DecimalFormat form = new DecimalFormat("$#0.00");

public static void main (String[] args) 
    {
        //Declare variables
        String input;
        String output;
        double payRate=0;
        double hourWrk=0;
        double income;

        //"for" loop to collect user input
        for (int count=0;count!=2;count++)
        {
            if (count==0)
                {input=JOptionPane.showInputDialog("Please enter your hourly pay: ");
                 payRate=Double.parseDouble(input);
                }
            else if (count==1)
                {input=JOptionPane.showInputDialog("Please enter your total hours "
                        + "worked for the past month: ");
                 hourWrk=Double.parseDouble(input);
                }
        }

        //Calculate and output final numbers

        income = payRate*hourWrk;

        //Declare the constants
        final double taxed = income-(.14*income);        // <---------
        final double cloth = .1*taxed;                   //The portion of code my
        final double supp = .01*taxed;                   //prof took issue with
        final double myBond = .25*taxed;                 // <---------
        final double prntBond = .5*myBond;

        output = 
                "Total Income (before tax): " + form.format(income) + "\n" +
                "Total Income (after tax): " + form.format(taxed) + "\n" +
                "----------------------------------------" + "\n" +
                "       Funds spent on Clothes: " + form.format(cloth) + "\n" +
                "       Funds spent on School Supplies: " + form.format(supp) + "\n" +
                "       Funds spent on Savings Bonds: " + form.format(myBond) + "\n" +
                "       Parent's funds spent on Savings Bonds: " + form.format(prntBond) + "\n" +
                "----------------------------------------" + "\n" +
                "Total Remaining Funds: " + form.format(taxed-(cloth+supp+myBond+prntBond));

        JOptionPane.showMessageDialog(null, output);
    } 
}

TL;DR - 我如何初始化/使用我的常量是否存在任何重大问题?

【问题讨论】:

  • 我没有在您的代码中看到常量。常量应该是在类级别声明的“最终静态”变量。
  • 是的,我不确定它们在技术上是否被认为是“常量”,但 final double 变量是我们的教授希望我们定义常量变量的方式(矛盾,我知道) 在课堂上。
  • @JoshMac 阅读答案更新
  • 你使用它的方式不是“常量”。然而,代码也没有错。一些 IDE 可以选择查看您的代码并在可能的情况下添加 final。对于 lambdas,Java 甚至现在也使用“有效最终”一词。 Java 是否真的有常量的概念值得商榷。
  • 你的代码很不错。你的变量没有问题。事实上,使用最终变量(一次写入变量)可能被认为是最佳实践!您的教授可能会将它们与 C 或 C++ 静态变量混淆,这些静态变量确实永远保持其值,即使跨函数调用也是如此。教授不完全精通他们教授的语言并不罕见。

标签: java constants final


【解决方案1】:

在计算机编程术语中,“常数”是一个在编译时已知的值,完全基于程序的源代码。该值可以是某些计算的结果,但唯一允许的输入是其他常量。例如,您可以定义一个值为2 * Math.PI 的常量。

在 Java 中,常量被声明为类的 static final 字段 - 也就是说,在所有方法之外,例如您放置 form 的位置。

您声明的是不能重新计算的局部变量,而不是常量。

现在,您可能想知道我刚才所说的内容如何与您的程序在循环中运行良好这一事实兼容。答案在于 Java 的变量范围规则。您的 final 变量在循环体中声明,这意味着它们的范围仅限于该循环体。此外,它仅限于循环体的单个迭代。您的循环运行一次,创建所有这些新的局部变量并为它们分配值,完成第一次运行,并丢弃这些变量。当它再次运行时,它不会重用相同的变量,而是创建一个全新的批次。当然,这个新批次可以像第一批次一样被初始化,所以程序继续工作。

【讨论】:

  • 好的,所以循环释放在其中声明的变量,就像被调用的方法在完成后释放其局部变量的内存一样? (我们今天刚刚了解了除 main 之外的方法,因此提出了问题)
  • @JoshMac 是的。 if 块,try/catch/finally 块(我猜你还没有学过),以及除了在一对 {} 中的类定义之外的几乎所有东西。你甚至可以添加一对像这样的花括号,根本不需要循环,只是为变量创建一个新的范围。当程序到达结束 } 时,它和匹配的 { 之间的变量消失。
  • 呵呵,有意思!我有点知道(我至少知道我可以重用循环中声明的变量),但我不知道为什么会发生这种情况,或者它发生在其他地方。是的,try/catch/finally 还没有被提及,但我的好奇心被激起了,因为我知道它存在......
【解决方案2】:

我认为您的老师主要是在抱怨您的代码中有文字值。这个想法是你提前定义你的文字常量以避免在你的代码中重复它们。 请参阅以下内容:

static final double INCOME_TAXE_RATE = .14;
static final double CLOTHING_TAXE_RATE = .1;
...
public static main(String[] args)

然后你可以按如下方式使用它们:

double taxed = income-(INCOME_TAXE_RATE * income);      
double cloth = CLOTHING_TAXE_RATE * taxed;              
...

声明文字常量的另一个好处是,如果您需要更新它们,您可以在代码中的一个位置进行更新。这使您的代码更具可读性和可维护性。

Java 不支持对象不变性的概念也很好,它不直接支持常量。 static 修饰符使变量在不加载类实例的情况下可用。最后修饰符使变量不可更改。这仅适用于原始数据类型。最终对象,仍然可以修改。

【讨论】:

    【解决方案3】:

    最好尽可能在字段中使用final 关键字,以避免多线程出现问题,并且您可以正常定义它。您的教授的意思是您将无法使用 final 关键字重新分配变量。但是在这种情况下你不需要它,所以没关系。

    【讨论】:

    • 好的,所以带有final 的变量不能重写它自己的赋值,但是在初始化时分配给final 变量的任何值/变量都可以改变它们自己的值,这会影响final 变量的输出?
    • @JoshMac 不,完全不对。您不将表达式或公式分配给变量,而是在执行赋值时分配表达式或公式的当前值。输入变量的后续更改不会影响final 变量的值。
    【解决方案4】:

    在您当前的应用程序中,您的常量与普通计算变量没有什么不同。实际上,通过计算应该在应用程序中使用的已知、已声明、预先计算的值,您浪费了一些 CPU 周期,实际上错过了将这些值声明为常量的意义。 p>

    考虑一下:如果您的所得税突然飙升至 40%,您需要做出哪些改变?如果你的债券跌到 1% 怎么办?常量可帮助您在理想情况下在一个清晰可见的位置进行更改。

    理想情况下,您的常数将代表您乘以的百分比。

    举个例子:

    final double incomeTax = .14;
    

    然后您就可以在表达式中使用incomeTax 来获得实际的净金额:

    double netIncome = income - (incomeTax * income);
    

    【讨论】:

    • @JoshMac:既然您才刚刚开始,请不要违反优化的第一条规则:不要这样做。无论如何,您的代码不会更优化,因为与加法相比,乘法的成本更高。
    • wasting a few CPU cycles 我想这是让我绊倒的原因;我的印象是这将是一个更有效的代码,因为它似乎没有做那么多的计算。实际上,我很早之前就提交了这个实验室——一个版本,我在其中编写了final 变量,正如你所展示的那样——但它显然丢失了,所以我以我认为更有效的方式重写了它。感谢您的帮助!
    • 哈哈,我一定要记住...还有什么优化规则我应该掌握吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-23
    • 1970-01-01
    • 2015-12-21
    • 2021-10-21
    • 2021-01-24
    • 1970-01-01
    相关资源
    最近更新 更多