Home > Java > javaTutorial > body text

Usage of inner classes and anonymous inner classes

高洛峰
Release: 2016-12-15 13:15:18
Original
2841 people have browsed it

1. Inner classes:

(1) Methods with the same name of the inner class

The inner class can call methods of the outer class. If the inner class has a method with the same name, it must be called using the "OuterClass.this.MethodName()" format (where OuterClass Replace MethodName with the actual external class name and its method; this is the keyword, indicating a reference to the external class); if the internal class does not have a method with the same name, you can directly call the method of the external class.
But peripheral classes cannot directly call private methods of inner classes, and external classes cannot directly call private methods of other classes. Note: The permission of the inner class to directly use the outer class has nothing to do with whether the method is static. It depends on whether the inner class has a method with the same name.

package innerclass;
public class OuterClass {
    private void outerMethod() {
        System.out.println("It's Method of OuterClass");
    }
    public static void main(String[] args) {
        OuterClass t = new OuterClass();
        OuterClass.Innerclass in = t.new Innerclass();
        in.innerMethod();
    }
 
    class Innerclass {
        public void innerMethod() {
           OuterClass.this.outerMethod();// 内部类成员方法与外部类成员方法同名时,使用this调用外部类的方法
           outerMethod();// 内部类没有同名方法时执行外部类的方法
        }
        private void outerMethod() {
            System.out.println("It's Method of Innerclass");
        }
    }
}
Copy after login

The output result is:

It's Method of OuterClass
It's Method of Innerclass
Copy after login

(2) Instantiation of inner classes

Instantization of inner classes is different from ordinary classes. Ordinary classes can be instantiated whenever needed, while inner classes must be instantiated after the outer class is instantiated Only then can it be instantiated and establish a relationship with the external class

So in the non-static method in the external class, the inner class object can be instantiated

private void outerMethod() {
    System.out.println("It's Method of OuterClass");
    Innerclass in = new Innerclass();//在外部类的outerMethod方法中实例化内部类是可以啊
}
Copy after login

But in the static method, you need to pay attention! ! ! ! You cannot directly new the inner class in the static method, otherwise an error will occur:

No enclosing instance of type OuterClass is accessible. Must qualify the allocation with an enclosing instance of type OuterClass (e.g. x.new A() where x is an instance of OuterClass).

This is because the static method can be used before the class is instantiated. It is called through the class name. At this time, the dynamic inner class has not been instantiated yet. How to use it? You cannot call something that does not exist. .

If you want to create a new inner class in the Static method, you can declare the inner class as Static

public class OuterClass {
    private void outerMethod() {
        System.out.println("It's Method of OuterClass");
    }
 
    public static void main(String[] args) {
        Innerclass in = new Innerclass();
        in.innerMethod();
    }
 
    static class Innerclass {//把内部类声明为static
        public void innerMethod() {
            System.out.println("It's Method of innerMethod");
 
        }
    }
 
}
Copy after login

Of course, the static method is generally not used, but this method is recommended: x.new A(), where x is the external class An instance of OuterClass, A is the inner class Innerclass

package innerclass;
public class OuterClass {
    private void outerMethod() {
        System.out.println("It's Method of OuterClass");
    }
    public static void main(String[] args) {
        OuterClass.Innerclass in = new OuterClass().new Innerclass();//使用x.new A()的方式
        in.innerMethod();
    }
    class Innerclass {
        public void innerMethod() {
            System.out.println("It's Method of innerMethod");
        }
    }
}
Copy after login

x.new A(), where x is an instance of the outer class OuterClass, A is the class class Innerclass, of course it can be split as follows, so it is obviously clear:

(3) When to use inner classes? The typical situation is that the inner class inherits from a certain class or implements a certain interface, and the code of the inner class operates the object of the outer class that created it. So you can think of inner classes as providing some kind of window into their outer classes.

The most attractive reason for using inner classes is that each inner class can independently inherit from an implementation (of the interface), so no matter whether the outer class has inherited an implementation of an (interface), for the inner class All have no effect. Without the ability provided by inner classes to inherit from multiple concrete or abstract classes, some design and programming problems would be difficult to solve. From this perspective, inner classes make the multiple inheritance solution complete. Interfaces solve part of the problem, while inner classes effectively implement "multiple inheritance."

(4) Example of instantiating an inner class in a static method: (The inner class is placed in a static method)

public static void main(String[] args) {
    OuterClass out = new OuterClass();//外部实例
    OuterClass.Innerclass in = out.new Innerclass();//外部实例.new 外部类
    in.innerMethod();
}
Copy after login

per.speak() can be called, but per.say() cannot be called, because per is Person Object, if you want to call the method of a subclass, you can force downcasting to: ((Boy) per).say(); or directly change to Boy per = new Boy();. It can be found that if you want to call a custom method of an inner class, you must call it through the object of the inner class. So, if the anonymous inner class doesn't even have a name, how can it call the custom method of the inner class?

(2) Anonymous inner classes

Anonymous inner classes are also inner classes without names. Because they have no names, anonymous inner classes can only be used once. They are usually used to simplify code writing, but using anonymous inner classes is also There is a prerequisite: you must inherit a parent class or implement an interface, but you can only inherit at most one parent class or implement an interface.

There are two more rules about anonymous inner classes:

1) Anonymous inner classes cannot be abstract classes, because when the system creates an anonymous inner class, it will immediately create an object of the inner class. Therefore, anonymous inner classes are not allowed to be defined as abstract classes.

2) Anonymous inner classes do not define constructors (constructors). Because anonymous inner classes have no class name, they cannot define a constructor, but anonymous inner classes can define instance initialization blocks.

How to determine the existence of an anonymous class? ? I can't see the name, it feels like it's just an object created by new from the parent class, and there is no name for the anonymous class.
Let’s look at the pseudocode first

package javatest2;
public class JavaTest2 {
    public static void main(String[] args) {
        class Boy implements Person {
            public void say() {// 匿名内部类自定义的方法say
                System.out.println("say方法调用");
            }
            @Override
            public void speak() {// 实现接口的的方法speak
                System.out.println("speak方法调用");
            }
        }
        Person per = new Boy();
        per.speak();// 可调用
        per.say();// 不能调用
    }
}
interface Person {
    public void speak();
}
Copy after login

Generally speaking, when new an object, there should be a semicolon after the parentheses, that is, the statement of new object ends. But it's different when there are anonymous inner classes. The parentheses are followed by braces, and the braces contain the specific implementation method of the new object. Because we know that an abstract class cannot be new directly. There must be an implementation class before we can new its implementation class. The above pseudocode indicates that new is the implementation class of Father, and this implementation class is an anonymous inner class.

In fact, splitting the anonymous inner class above can be:

abstract class Father(){
....
}
public class Test{
   Father f1 = new Father(){ .... }  //这里就是有个匿名内部类
}
Copy after login

Let’s look at an example first to experience the usage of anonymous inner classes:


运行结果:eat something
可以看到,我们直接将抽象类Person中的方法在大括号中实现了,这样便可以省略一个类的书写。并且,匿名内部类还能用于接口上

public class JavaTest2 {
    public static void main(String[] args) {
        Person per = new Person() {
            public void say() {// 匿名内部类自定义的方法say
                System.out.println("say方法调用");
            }
            @Override
            public void speak() {// 实现接口的的方法speak
                System.out.println("speak方法调用");
            }
        };
        per.speak();// 可调用
        per.say();// 出错,不能调用
    }
}
 
interface Person {
    public void speak();
}
Copy after login

这里per.speak()是可以正常调用的,但per.say()不能调用,为什么呢?注意Person per = new Person()创建的是Person的对象,而非匿名内部类的对象。其实匿名内部类连名字都没有,你咋实例对象去调用它的方法呢?但继承父类的方法和实现的方法是可以正常调用的,本例子中,匿名内部类实现了接口Person的speak方法,因此可以借助Person的对象去调用。

若你确实想调用匿名内部类的自定义的方法say(),当然也有方法:

(1)类似于speak方法的使用,先在Person接口中声明say()方法,再在匿名内部类中覆写此方法。

(2)其实匿名内部类中隐含一个匿名对象,通过该方法可以直接调用say()和speak()方法;代码修改如下:

public class JavaTest2 {
    public static void main(String[] args) {
        new Person() {
            public void say() {// 匿名内部类自定义的方法say
                System.out.println("say方法调用");
            }
 
            @Override
            public void speak() {// 实现接口的的方法speak
                System.out.println("speak方法调用");
            }
        }.say();// 直接调用匿名内部类的方法
    }
}
interface Person {
    public void speak();
}
Copy after login


更多内部类和匿名内部类的用法相关文章请关注PHP中文网!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template