Home  >  Article  >  Java  >  Inner classes and anonymous classes in Java

Inner classes and anonymous classes in Java

高洛峰
高洛峰Original
2016-12-15 12:41:301359browse

Java Inner Class, a similar concept is also found in C++, that is, Nested Class. At first glance, inner classes seem a bit redundant, and its usefulness may not be so obvious to beginners. , but with a deeper understanding of it, you will find that the designers of Java do have good intentions in internal classes. Learning to use inner classes is part of mastering advanced Java programming, which allows you to design your program structure more elegantly. Let’s introduce it from the following aspects:

First meeting

public interface Contents {
    int value();
}
public interface Destination {
    String readLabel();
}
public class Goods {
    private class Content implements Contents {
        private int i = 11;
        public int value() {
            return i;
        }
    }
    protected class GDestination implements Destination {
        private String label;
        private GDestination(String whereTo) {
            label = whereTo;
        }
        public String readLabel() {
            return label;
        }
    }
    public Destination dest(String s) {
        return new GDestination(s);
    }
    public Contents cont() {
        return new Content();
    }
}
class TestGoods {
    public static void main(String[] args) {
        Goods p = new Goods();
        Contents c = p.cont();
        Destination d = p.dest("Beijing");
    }
}

In this example, the classes Content and GDestination are defined inside the class Goods, and have protected and private modifiers respectively to control the access level. Content represents the content of Goods, and GDestination represents the destination of Goods. They implement two interfaces Content and Destination respectively. In the following main method, you directly use Contents c and Destination d to operate. You don't even see the names of these two internal classes! In this way, the first benefit of inner classes is reflected - hiding operations that you don't want others to know, that is, encapsulation.

At the same time, we also discovered the first way to get an inner class object outside the scope of the outer class, which is to create and return it using the methods of its outer class. The cont() and dest() methods in the above example do this. So is there any other way? Of course, the syntax format is as follows:

outerObject=new outerClass(Constructor Parameters);
outerClass.innerClass innerObject=outerObject.new InnerClass(Constructor Parameters);

Note that when creating a non-static inner class object, you must first create the corresponding outer class object. As for the reason, this leads to our next topic -

Non-static inner class objects have references to their outer class objects

Slightly modified the example just now:

public class Goods {
    private valueRate=2;
    private class Content implements Contents {
        private int i = 11*valueRate;
        public int value() {
            return i;
        }
    }
    protected class GDestination implements Destination {
        private String label;
        private GDestination(String whereTo) {
            label = whereTo;
        }
        public String readLabel() {
            return label;
        }
    }
    public Destination dest(String s) {
        return new GDestination(s);
    }
    public Contents cont() {
        return new Content();
    }
}

The modified part is shown in red. Here we add a private member variable valueRate to the Goods class, which means the value coefficient of the goods. It is multiplied by it when the value() method of the internal class Content calculates the value. We found that value() can access valueRate, which is also the second benefit of inner classes - an inner class object can access the contents of the outer class object that created it, even private variables! This is a very useful feature that provides us with more ideas and shortcuts when designing. To achieve this function, the inner class object must have a reference to the outer class object. When the Java compiler creates an inner class object, it implicitly passes the reference to its outer class object and keeps it. This allows the inner class object to always access its outer class object, and this is also why to create an inner class object outside the scope of the outer class, you must first create its outer class object.

Someone may ask, what should I do if a member variable in the inner class has the same name as a member variable in the outer class, that is, the member variable with the same name in the outer class is blocked? It’s okay, Java uses the following format to express references to external classes:

outerClass.this

With it, we are not afraid of this kind of shielding.

Static inner classes

Like ordinary classes, inner classes can also be static. However, compared with non-static inner classes, the difference is that static inner classes have no external references. This is actually very similar to nested classes in C++. The biggest difference between Java internal classes and C++ nested classes is whether there are references to the outside. Of course, from a design perspective and some of its details, There is a difference.

In addition, in any non-static inner class, there cannot be static data, static methods or another static inner class (the nesting of inner classes can be more than one level). But you can have all this in static inner classes. This can be regarded as the second difference between the two.

Partial inner classes

Yes, Java inner classes can also be local, it can be defined within a method or even a code block.

public class Goods1 {
     public Destination dest(String s) {
          class GDestination implements Destination {
               private String label;
               private GDestination(String whereTo) {
                    label = whereTo;
               }
               public String readLabel() { return label; }
          }
          return new GDestination(s);
     }
     public static void main(String[] args) {
          Goods1 g= new Goods1();
          Destination d = g.dest("Beijing");
     }
}

The above is such an example. In the method dest, we define an inner class, and finally this method returns the object of this inner class. If we only need to create an object of an inner class and create it to the outside, we can do this. Of course, inner classes defined in methods can diversify the design, and their uses are not limited to this.

Here is a weirder example:

public class Goods2{
     private void internalTracking(boolean b) {
          if(b) {
               class TrackingSlip {
                    private String id;
                    TrackingSlip(String s) {
                         id = s;
                    }
                    String getSlip() { return id; }
               }
               TrackingSlip ts = new TrackingSlip("slip");
               String s = ts.getSlip();
          }
     }
     public void track() { internalTracking(true); }
     public static void main(String[] args) {
          Goods2 g= new Goods2();
          g.track();
     }
}

You cannot create an object of this inner class outside if, because this has exceeded its scope. However, during compilation, the internal class TrackingSlip is compiled at the same time as other classes, except that it has its own scope and is invalid beyond this scope. Other than that, it is no different from other internal classes.

Anonymous inner class

The syntax rules of Java's anonymous inner class may seem a little weird, but like anonymous arrays, when you only need to create an object of a class and don't need its name, using inner classes can make the code It looks concise and clear. Its grammatical rules are as follows:

new interfacename(){......}; 或 new superclassname(){......};

Let’s continue with the example below:

public class Goods3 {
     public Contents cont(){
          return new Contents(){
               private int i = 11;
               public int value() {
                    return i;
               }
          };
     }
}

这里方法cont()使用匿名内部类直接返回了一个实现了接口Contents的类的对象,看上去的确十分简洁。

在java的事件处理的匿名适配器中,匿名内部类被大量的使用。例如在想关闭窗口时加上这样一句代码:

frame.addWindowListener(new WindowAdapter(){
     public void windowClosing(WindowEvent e){
          System.exit(0);
     }
});

    有一点需要注意的是,匿名内部类由于没有名字,所以它没有构造函数(但是如果这个匿名内部类继承了一个只含有带参数构造函数的父类,创建它的时候必须带上这些参数,并在实现的过程中使用super关键字调用相应的内容)。如果你想要初始化它的成员变量,有下面几种方法:

如果是在一个方法的匿名内部类,可以利用这个方法传进你想要的参数,不过记住,这些参数必须被声明为final。

将匿名内部类改造成有名字的局部内部类,这样它就可以拥有构造函数了。

在这个匿名内部类中使用初始化代码块。

为什么需要内部类?

java内部类有什么好处?为什么需要内部类?

    首先举一个简单的例子,如果你想实现一个接口,但是这个接口中的一个方法和你构想的这个类中的一个方法的名称,参数相同,你应该怎么办?这时候,你 可以建一个内部类实现这个接口。由于内部类对外部类的所有内容都是可访问的,所以这样做可以完成所有你直接实现这个接口的功能。

    不过你可能要质疑,更改一下方法的不就行了吗?

    的确,以此作为设计内部类的理由,实在没有说服力。

    真正的原因是这样的,java中的内部类和接口加在一起,可以的解决常被C++程序员抱怨java中存在的一个问题——没有多继承。实际上,C++的多继承设计起来很复杂,而java通过内部类加上接口,可以很好的实现多继承的效果。

  java内部类总结

(1)  在方法间定义的非静态内部类: 

       ● 外围类和内部类可互相访问自己的私有成员。

       ● 内部类中不能定义静态成员变量。

           在外部类作用范围之外向要创建内部类对象必须先创建其外部类对象

 

(2) 在方法间定义的静态内部类:

       ● 只能访问外部类的静态成员。

         静态内部类没有了指向外部的引用

 

(3) 在方法中定义的局部内部类:

       ● 该内部类没有任何的访问控制权限

       ● 外围类看不见方法中的局部内部类的,但是局部内部类可以访问外围类的任何成员。

       ● 方法体中可以访问局部内部类,但是访问语句必须在定义局部内部类之后。

       ● 局部内部类只能访问方法体中的常量,即用final修饰的成员。

 

(4) 在方法中定义的匿名内部类:

       ● 没有构造器,取而代之的是将构造器参数传递给超类构造器

            当你只需要创建一个类的对象而且用不上它的名字时,使用匿名内部类可以使代码看上去简洁清楚。


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

Statement:
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