3

我遇到了以下 java 代码,但我不确定它的含义。我们可以在实例化一个类之后在'{'中编写代码吗,例如 new TestClass { */ code goes here */ }

但是当我尝试运行代码时,我在输出中看不到“Z 为 10”。有人可以给我一些链接,我可以在其中获得与 java 的此功能相关的更多信息。

class TestClass {
    int z;
    public TestClass(){
    z=10;
    }
    public int getZ(){
    return z;
    }
    public void setZ(int z){
    this.z=z;
    }
}

class A
{   
    public static void main (String[] args) throws java.lang.Exception
    {
    TestClass TC = new TestClass() {
            public void testprint() {
        System.out.println("Z is " + getZ());
        }
     };
    }
}
4

5 回答 5

8

这是一个匿名内部类。它创建了一个对象,该对象是某个类的子类 TestClass 的实例,您不想为该子类命名(因为您只需要动态创建对象,并且不需要在任何地方使用该类别的)。

代码仅初始化对象,您实际上并没有调用您正在创建的对象的方法,所以这就是您看不到任何输出的原因。您可以在代码中添加一行

public static void main (String[] args) throws java.lang.Exception
{
    TestClass TC = new TestClass() {
        public void testprint() {
            System.out.println("Z is " + getZ());
        }
    };
    // <- call the new method (>_< this won't compile)
    TC.testprint(); 
}

除了这不起作用,因为 testprint 没有定义为 TestClass 上的方法,引用对象的局部变量具有 TestClass 类型,因此编译器希望找到在 TestClass 或 TestClass 的超类上定义的方法。您可以向 TestClass 添加某种方法,如下所示:

abstract class TestClass {
    int z;
    public TestClass(){
        z=10;
    }
    public int getZ(){
        return z;
    }
    public void setZ(int z){
        this.z=z;
    }
    // add new method
    public abstract void testprint();
}

现在编译器知道期望 TestClass 类型的对象将有一个称为 testprint 的方法。我不必使 TestClass 抽象,我可以向它添加一个 testprint 的实现。但是,因为 TestClass 是抽象的,所以很明显新对象不是 TestClass,而是它的某个子类。

或者,通过 TestClass 的其他已公开方法调用此方法。使用您的 TestClass 不变,但将主要方法更改为:

public static void main (String[] args) throws java.lang.Exception
{
    TestClass TC = new TestClass() {
        public void testprint() {
            System.out.println("Z is " + super.getZ());
        }
        // override Z getter to call testprint
        @Override public int getZ(){ 
            testprint();
            return z;
        }
    };
    TC.getZ(); // <- call method on object created above
}

testprint 必须更改以调用 Z 的 getter 的超类版本,因此我们不会有无限递归。现在匿名子类上的 Z getter 调用 testprint 方法,因此您可以调用 getter 并查看输出:

Z is 10

该代码没有为子类分配名称,但仍会为其分配一个名称。如果我在 main 的末尾添加一行以查看内部调用的匿名类:

    System.out.println(TC.getClass());

它打印

class A$1

实际上,不能直接调用在匿名类中定义的新方法并不是限制。如果您想将类的实现传递给其他对象的方法,则提供匿名类,获取匿名类对象的东西不知道(也不应该知道,请参阅LSP)如何无论如何都要调用新方法。

于 2014-04-25T13:32:40.027 回答
2

它是匿名内部类的例子。它就像一个扩展TestClass的类。所以你没有调用该类的任何方法,所以它不会打印

于 2014-04-25T13:31:24.950 回答
1

这样做时,您会TestClass立即隐式继承和实例化它,添加一个 method testPrint()

这称为匿名类

于 2014-04-25T13:31:15.997 回答
1

在您的代码中

TestClass TC = new TestClass() {
            public void testprint() {
        System.out.println("Z is " + getZ());
        }
     };

这被称为匿名内部类所以这只会初始化。您可以 TC.testprint();在上面的代码片段之后使用。

注意 - TC 没问题。但根据 Java 命名约定规则使用简单字母。您可以从这里阅读更多信息 - http://www.iwombat.com/standards/JavaStyleGuide.html

于 2014-04-25T13:43:41.317 回答
0

这称为匿名类。它在幕后所做的是创建一个扩展给定类或实现给定接口的子类。您可以在此处阅读有关匿名类的更多信息:http: //docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html

于 2014-04-25T13:36:36.540 回答