在Bruce Eckel的com.bruceeckel.simpletest包里面,有两个文件Test.java和OutputVerifier.java.
类Test和类OutputVerifier互相引用了。编译时分别出错。请问Java里面(或者更进一步说,面向对象语言里面)是否允许类的互相引用的?如果可以引用那么应该怎样编译通过呢?如果不允许,那么Bruce Eckel先生是否犯了一个错误?Test.java(用到OutputVerifier处加了//*******注释)//: com:bruceeckel:simpletest:Test.java
// Simple utility for testing program output. Intercepts
// System.out to print both to the console and a buffer.
// From 'Thinking in Java, 3rd ed.' (c) Bruce Eckel 2002
// www.BruceEckel.com. See copyright notice in CopyRight.txt.
package com.bruceeckel.simpletest;
import java.io.*;
import java.util.*;
import java.util.regex.*;public class Test {
  // Bit-shifted so they can be added together:
  public static final int
    EXACT = 1 << 0, // Lines must match exactly
    AT_LEAST = 1 << 1, // Must be at least these lines
    IGNORE_ORDER = 1 << 2, // Ignore line order
    WAIT = 1 << 3; // Delay until all lines are output
  private String className;
  private TestStream testStream;
  public Test() {
    // Discover the name of the class this
    // object was created within:
    className =
      new Throwable().getStackTrace()[1].getClassName();
    testStream = new TestStream(className);
  }
  public static List fileToList(String fname) {
    ArrayList list = new ArrayList();
    try {
      BufferedReader in =
        new BufferedReader(new FileReader(fname));
      try {
        String line;
        while((line = in.readLine()) != null) {
          if(fname.endsWith(".txt"))
            list.add(line);
          else
            list.add(new TestExpression(line));
        }
      } finally {
        in.close();
      }
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
    return list;
  }
  public static List arrayToList(Object[] array) {
    List l = new ArrayList();
    for(int i = 0; i < array.length; i++) {
      if(array[i] instanceof TestExpression) {
        TestExpression re = (TestExpression)array[i];
        for(int j = 0; j < re.getNumber(); j++)
          l.add(re);
      } else {
        l.add(new TestExpression(array[i].toString()));
      }
    }
    return l;
  }
  public void expect(Object[] exp, int flags) {
    if((flags & WAIT) != 0)
      while(testStream.numOfLines < exp.length) {
        try {
          Thread.sleep(1000);
        } catch (InterruptedException e) {
          throw new RuntimeException(e);
        }
      }
      List output = fileToList(className + "Output.txt");
      if((flags & IGNORE_ORDER) == IGNORE_ORDER)
        OutputVerifier.verifyIgnoreOrder(output, exp); //***********
      else if((flags & AT_LEAST) == AT_LEAST)
        OutputVerifier.verifyAtLeast(output, //*************
          arrayToList(exp));
      else
        OutputVerifier.verify(output, arrayToList(exp));
    // Clean up the output file - see c06:Detergent.java
    testStream.openOutputFile();
  }
  public void expect(Object[] expected) {
    expect(expected, EXACT);
  }
  public void expect(Object[] expectFirst,
    String fname, int flags) {
    List expected = fileToList(fname);
    for(int i = 0; i < expectFirst.length; i++)
      expected.add(i, expectFirst[i]);
    expect(expected.toArray(), flags);
  }
  public void expect(Object[] expectFirst, String fname) {
    expect(expectFirst, fname, EXACT);
  }
  public void expect(String fname) {
    expect(new Object[] {}, fname, EXACT);
  }
} ///:~
OutputVerifier.java (用到Test处加了//******注释)//: com:bruceeckel:simpletest:OutputVerifier.java
// From 'Thinking in Java, 3rd ed.' (c) Bruce Eckel 2002
// www.BruceEckel.com. See copyright notice in CopyRight.txt.
package com.bruceeckel.simpletest;
import java.util.*;
import java.io.PrintStream;public class OutputVerifier {
  private static void verifyLength(
    int output, int expected, int compare) {
    if((compare == Test.EXACT && expected != output) //******
      || (compare == Test.AT_LEAST && output < expected))
      throw new NumOfLinesException(expected, output);
  }
  public static void verify(List output, List expected) {
    verifyLength(output.size(),expected.size(),Test.EXACT);
    if(!expected.equals(output)) {
      //find the line of mismatch
      ListIterator it1 = expected.listIterator();
      ListIterator it2 = output.listIterator();
      while(it1.hasNext()
        && it2.hasNext()
        && it1.next().equals(it2.next()));
      throw new LineMismatchException(
        it1.nextIndex(), it1.previous().toString(),
        it2.previous().toString());
    }
  }
  public static void
  verifyIgnoreOrder(List output, Object[] expected) {
    verifyLength(expected.length,output.size(),Test.EXACT);
    if(!(expected instanceof String[]))
      throw new RuntimeException(
        "IGNORE_ORDER only works with String objects");
    String[] out = new String[output.size()];
    Iterator it = output.iterator();
    for(int i = 0; i < out.length; i++)
      out[i] = it.next().toString();
    Arrays.sort(out);
    Arrays.sort(expected);
    int i =0;
    if(!Arrays.equals(expected, out)) {
      while(expected[i].equals(out[i])) {i++;}
      throw new SimpleTestException(
        ((String) out[i]).compareTo(expected[i]) < 0
          ? "output: <" + out[i] + ">"
          : "expected: <" + expected[i] + ">");
    }
  }
  public static void
  verifyAtLeast(List output, List expected) {
    verifyLength(output.size(), expected.size(),
      Test.AT_LEAST);
    if(!output.containsAll(expected)) {
      ListIterator it = expected.listIterator();
      while(output.contains(it.next())) {}
      throw new SimpleTestException(
        "expected: <" + it.previous().toString() + ">");
    }
  }
} ///:~

解决方案 »

  1.   

    我想问一下 请问thinking in java 这本书在网上可以找到吗? 很想看看  谢谢拉!~!!!~
      

  2.   

    到http://www.mindview.net/Books/TIJ下载
      

  3.   

    可以吧
    class first 
    {
    public static void main(String[] args) 
    {
    System.out.println("Hello ");
    new second().printStr();
    }
    public void printStr(){
    System.out.println("Hello ");
    }
    }class second 
    {
    public static void main(String[] args) 
    {
    System.out.println("World!");
    new first().printStr();
    }
    public void printStr(){
    System.out.println("World!");
    }
    }
      

  4.   

    当然,除了构造函数外
    如果两个函数之间互相引用的话也会出现问题
    就相当于出现了一个没有结束条件的递归
    会报stack overflow的错误比如把 nanfengJava(楠枫JAVA)的函数改成这样:class first 
    {
    public static void main(String[] args) 
    {
    System.out.println("Hello ");
    new second().printStr();
    }
    public void printStr(){
    System.out.println("Hello ");
    new second().printStr();
    }
    }
    class second 
    {
    public static void main(String[] args) 
    {
    System.out.println("World!");
    new first().printStr();
    }
    public void printStr(){
    System.out.println("World!");
    new first().printStr();
    }
    }
      

  5.   

    但是编译的时候怎么办呢?如果一个文件一个文件的编译是一定不成的。是不是放到同一个Project文件里面?或者有其他的方法?
      

  6.   

    行不行自己试下就知道了我就是一个一个编译的,就用sun的jdk
      

  7.   

    我当然试过了,不试我怎么会提出问题?我是放到一个Project里面编译的,可以。但是一个一个编译就不行。
      

  8.   

    首先谢谢zhangqingqi82和nanfengjava。
    如zhangqingqi82所言,一个一个编译是可以的。
    如nanfengjava的程序,编译first.java的时候,系统会把second.java也编译了(有点奇怪)。
    但是,我编译thinkingInJava的例程的时候,同样是两个类互相引用,系统却不会把其他文件也一起编译。原因不清楚。class first 
    {
    public static void main(String[] args) 
    {
    System.out.println("Hello ");
    new second().printStr();
    }
    public void printStr(){
    System.out.println("Hello ");
    }
    }class second 
    {
    public static void main(String[] args) 
    {
    System.out.println("World!");
    new first().printStr();
    }
    public void printStr(){
    System.out.println("World!");
    }
    }
      

  9.   

    互相引用???我想还谈不上..
    它只是在OutputVerifier类中用了Test类的一个静态常量...
    以及在Test类中调用了OutputVerifier静态方法,像这种方法和变量是可以直接由类名.名称来调用的.
    不存在互相引用..
    如果在Test类的构造函数中生成OutputVerifier的对象,而在OutputVerifier类的构造函数又生成TestOutputVerifier的对象,刚构成互相引用.