在实例化类时声明函数

时间:2014-04-25 13:28:21

标签: java anonymous-inner-class

我遇到了以下java代码,我不确定它是什么意思。我们可以在' {'在我们实例化一个类之后,例如新的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());
        }
     };
    }
}

5 个答案:

答案 0 :(得分: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的impelmentation。但是,因为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

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

答案 1 :(得分:2)

这是匿名内部类的例子。它就像一个扩展TestClass的类。因此,您不会调用该类的任何方法,因此不会打印

答案 2 :(得分:1)

执行此操作时,您将隐式子类化TestClass并立即对其进行实例化,并添加方法testPrint()

这称为Anonymous Class

答案 3 :(得分:1)

在您的代码中

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

这称为Annonymous Inner Class所以这只会初始化。您可以在上面的代码段后使用TC.testprint();

注意 - TC没问题。但根据Java命名约定规则使用简单的字母。 您可以在此处阅读更多内容 - http://www.iwombat.com/standards/JavaStyleGuide.html

答案 4 :(得分:0)

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