【问题标题】:Running number in a Class班级中的流水号
【发布时间】:2014-07-20 20:11:00
【问题描述】:

在下面的示例中,我试图生成一个运行作为 class::Product 的简单 ID。然而,结果却出乎我的意料。

我的代码

public class myProgram
{
   public static void main(String[] args)
   {
      Product product1 = new Product("AAA");
      Product product2 = new Product("BBB");
      Product product3 = new Product("CCC");

      System.out.println(product1.printItem());                 
      System.out.println(product2.printItem());
      System.out.println(product3.printItem());
   }
}

class Product
{
   static int productID = 0;
   String name;

   public Product(String startName)
   {
      productID ++;
      name = startName;
   }

   public int printItem()
   {
      return productID;
   }
}

计划成果

3
3
3

我期望它得到的结果是:

1
2
3

我的问题:我做错了什么导致错误的程序输出?

编辑 1: 我放置了一个静态关键字,希望它在每次创建实例后增加 ProductID(而不是每次都重置回 0)。如果没有,如何生成流水号?

【问题讨论】:

  • 因为产品 id 是静态变量?
  • @KickButtowski 我故意将其设为静态,希望它在创建每个对象实例后添加 1。如果不是,它会一直保持为 0?
  • 因为它是一种通用变量类型。每个人都可以更新它。如果你想要你的预期结果,你根本不应该使用静态变量

标签: java class static count


【解决方案1】:

因为productId 是静态的,所以每个实例一次只有一个全局值,为了匹配您的预期输出,您需要每个实例都有一个本地id。另外,我建议您将printItem() 替换为toString() 和/或getItem()。最后,为了线程安全,您可能应该使用AtomicInteger

class Product {
  static AtomicInteger productCount = new AtomicInteger(0);
  int productID = 0;
  String name;

  public Product(String startName) {
    productID = productCount.addAndGet(1);
    name = startName;
  }

  public int getItemId() {
    return productId;
  }

  @Override
  public String toString(){
    return String.valueOf(productID);
  }
}

【讨论】:

  • 我已经在使用 toString() 进行打印,实际上我在这里重新输入了所有代码以使其更简单并直接解决我的问题。
  • 注意:++ 不是原子的,所以在多线程环境中最好使用AtomicInteger 作为productCount 类型。
  • @Pshemo 已编辑。好建议。
  • @ElliottFrisch 过度设计您的解决方案并不总是一个好主意。有时最好让代码做需要做的事情。如果我们有超过 20 亿个产品,我们可以使用 AtomicLong 来代替,添加 equals、hashCode、compareTo、缓存 toString(),如果我们添加所有我们认为可能需要的东西,在哪里停止。 ;)
  • @PeterLawrey 虽然有时玻璃杯比实际需要的大一倍,但要装一品脱啤酒,您需要一品脱玻璃杯!
【解决方案2】:

您有一个static 字段,这意味着只有一个值。您可能打算拥有一个静态字段作为您的计数器和一个成员非静态字段来保存该值。

尝试改变

static int counter = 0;
int productID = 0;
String name;

public Product(String startName) {
    productID = ++counter;

如果您在调试器中单步调试您的代码,您会看到您的程序实际在做什么。

【讨论】:

  • @ThomasJunk OP 似乎使用了多少线程? ;)
  • 在他的生活中是真的还是曾经?
  • @ThomasJunk 这门课在他的生活中可能会做很多事情,为什么要特别选择那个。我本来很想添加 equals/hashCode,例如在我的 IDE 中使用代码生成,但这并不是一个好主意。
  • @ThomasJunk “与工程师争论很像与猪在泥泞中摔跤。几个小时后,你就会意识到他喜欢它。”
【解决方案3】:

因为静态变量在所有对象只有一个副本的对象之间共享。你可以说全班一份。

静态变量(或类变量)是属于类本身的变量,而不是属于类的对象。

参见Understanding Class Members上的Java 教程

Read more...

尝试从视觉上理解它。

【讨论】:

  • 我试图理解其中的逻辑,你说得非常清楚和直截了当。为你+1。谢谢!
【解决方案4】:

你有

static int productID = 0;

这里static 表示productID 属于Product 类而不属于Product 的实例。所有实例共享相同ProductID

改为使用

int productID = 0

然后每个实例都有自己的副本。您将需要找到另一种设置值的方法...

【讨论】:

    【解决方案5】:

    因为您已将 ProductID 设为静态,所以它的值将由 Product 类型的所有对象共享。我的建议是在你的 main 函数中创建一个变量,每次创建产品时递增该变量并将其作为参数传递。

    编辑:@DavidPostill -- 那么它们都将等于 1。

    【讨论】:

      【解决方案6】:

      因为productID 被定义为static

      注意:静态变量的值对于类的所有对象(或实例)都是相同的,或者换句话说,您可以说同一类的所有实例(对象)共享静态变量的单个副本。

      来源:http://beginnersbook.com/2013/05/static-variable/

      【讨论】:

        猜你喜欢
        • 2013-06-24
        • 2019-04-26
        • 1970-01-01
        • 2019-07-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-09
        • 1970-01-01
        相关资源
        最近更新 更多