【问题标题】:Are these java classes equivalent?这些java类是等价的吗?
【发布时间】:2013-07-10 19:39:16
【问题描述】:

给定以下 2 个类 Example1 和 Example2 并排除所有性能特征,这两个类的操作方式是否完全相同。也就是说,无论 methodA 或 methodB 多么简单或复杂,在所有可能的条件下(内部和外部)运行这两个类的结果是否总是绝对相同 ?

示例1

public class Example1
{
    public static void main (String [] args)
    {
        try
        {   
            // this will not compile since nextBoolean() is not static
            // boolean t = java.util.Random.nextBoolean();

            // changed to
            java.util.Random r = new java.util.Random();
        boolean t = r.nextBoolean();

            if (t)
            {
                methodA();
                methodB();
            }
        }
        catch (Throwable t)
        {
            t.printStackTrace(System.out);
        }
    }

    private static void methodB ()
    {
        // code goes here
    }

    private static void methodA ()
    {
        // code goes here
    }
}

示例2

public class Example2
{
    public static void main (String [] args)
    {
        try
        {   
            boolean t = java.util.Random.nextBoolean();

            if (t)
            {
                methodA();
            }

            if (t)
            {
                methodB();
            }
        }
        catch (Throwable t)
        {
            t.printStackTrace(System.out);
        }
    }

    private static void methodB ()
    {
        // code goes here
    }

    private static void methodA ()
    {
        // code goes here
    }
}

【问题讨论】:

  • 是的,他们会给你同样的输出。
  • 您基本上是在问if 语句在Java 语言中是否可靠地工作?我打算出去说它确实如此。
  • 这取决于您所说的“相同方式”。由于Random.nextBoolean 调用引入的随机性,两次执行不一定会产生相同的结果。但是,它们都遵循相同的执行路径,因为它们都将以相同的顺序对相同的变量执行相同的操作,只是 Random 引入了可变性,因为种子发生了变化(这是输入之一)。

标签: java class equivalent


【解决方案1】:

是的,它们是一样的。基本上问题是问这两件事是否相等:

        if (t)
        {
            methodA();
            methodB();
        }

        if (t)
        {
            methodA();
        }

        if (t)
        {
            methodB();
        }

它们是相同的,因为t 不能在方法调用之间改变。

【讨论】:

    【解决方案2】:

    是的,它们会产生相同的输出。变量t不能被方法改变,所以methodA不可能阻止methodB执行。

    同样,如果methodA 抛出异常,methodB 在这两种情况下都不会执行。

    【讨论】:

    • 我觉得重要的是要注意,如果t 是一个方法调用,那么这些就不一样了。抛开性能不谈,一个人会调用if 语句的方法两次,另一个人会调用一次。这是一个非常重要的区别,如果所讨论的方法确实做了一些事情。
    【解决方案3】:

    结果保证绝对相同,但一般情况下会如此。具体来说,您可以编写一个methodAmethodB 实现,在Example1Example2 中运行时会产生不同的结果,即使在执行之前主程序的类名相同。

    实现此目的的一种方法是生成堆栈跟踪,然后自省执行methodB 的行号,这在Example1Example2 中是不同的。

    例如下面的方法B在Example1Example2运行时会产生不同的输出。

    public static void methodB()
    {
        int count = 0;
    
        StackTraceElement[] elements = Thread.currentThread().getStackTrace();
        for (StackTraceElement element : elements)
        {
            count += element.getLineNumber();
        }
    
        System.out.println(count);
    }
    

    但是,通常程序会产生相同的结果,因为这种基于堆栈跟踪或其他此类方面的逻辑是不寻常的。

    【讨论】:

    • 有趣的开箱即用答案;但是,如果代码在Example1 中编写为if (t){methodA();methodB();},在Example2 中编写为if (t){methodA();} if (t){methodB();},我们仍然可以从System.out.println(count); 获得相同的输出。但是,可以说我最初的问题并不是所有这些陈述都在一行中提出的。
    • @user2512399 是的,非常正确。但是,即使这样,您也可以通过从磁盘读取类文件并根据原始字节做一些事情来区分,假设编译器没有优化并产生相同的字节码。我只发布了这个答案,因为您要求绝对保证,无论多么复杂等等。
    【解决方案4】:

    它们是一样的。 if 语句在两个类中是相同的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-07
      相关资源
      最近更新 更多