• 内部类(inner class)的简单介绍


    本文主要介绍内部类(inner class)的一些基本应用,将从内部类的分类角度,首先对每一个具体内部类进行介绍。主要包括普通的内部类【common inner class】、局部内部类[local inner class]、嵌套内部类【nested innner class】、匿名内部类【anonymous inner class】、然后比较一下局部内部类[local inner class]和匿名内部类【anonymous inner class ]的区别,进而知道在具体情况下该选择内部类,即到底用local inner class还是anonymous inner class。最后介绍内部类的应用

    一:首先对每一个具体内部类进行介绍

    1.普通的内部类【common inner class】

    定义:在一个类里面直接定义一个类:

    一些详细情况看代码:

     1 package com.qls.comonInnerClass;
     2 
     3 public class A {
     4     /**
     5      * 从B C D E 这四个普通内部类中可以看出类前面的修饰符可以是
     6      * private  protected default(也就是什么修饰符没有的D) public.  而在局部内部类中修饰类的只能是:
     7      * abstract 或final 或者什么修饰符都没有。
     8      * 注意的问题如下:
     9      * 1.通常情况下:外部类会有一个返回内部类引用的一个方法如getB()这个方法。
    10      * 2.如何在内部类中用this指代外部类引用?【答:外部类名.this 参考第19行代码。】
    11      * 以及如何创建内部类的一个实例?【答:x.new B() 其中x是外部类的一个实例,B为一个内部类。
    12      * 若是直接写new B()会报错。参考第38、39两行代码。】
    13      * 上述两个注意点对其他的内部类也适用。
    14      * @author 秦林森
    15      *
    16      */
    17     private  class B {
    18         public A outer(){
    19             return A.this;//A.this是指代A的一个引用。
    20         }
    21     }
    22     protected class C{
    23         
    24     }
    25     class D{
    26         
    27     }
    28     public class E{
    29         
    30     }
    31     /**
    32      * 返回内部类的引用:
    33      */
    34     B getB(){
    35         return new B();
    36     }
    37     public static void main(String[] args) {
    38         A a = new A();
    39         B b = a.new B();
    40     }
    41 }

    局部内部类【local innner class】

    定义:把类定义在方法里面,或者是方法中的某一个区域中。

    代码如下:

     1 package com.qls.localInnerClass2;
     2 /**
     3  * 定义:the creation of an entire class within the scope of a method,or Nesting a class within 
     4  * a scope of a method.
     5  * This is called a local inner class.
     6  * 注意情况如下:
     7  * 1.局部内部类【local inner class】如果想要修饰的话,只有abstract 和final可以,
     8  * 其余的如(public protected)等都不可以。
     9  * 2.在局部内部类中只能访问包含该内部类的范围(enclosing scope)的final变量。若不是则会报错。
    10  * 
    11  * @author 秦林森
    12  *
    13  */
    14 public class A {
    15     public void ouyangfeng(){
    16         //把类D定义在方法ouyangfeng()的某个区域中。
    17         if(3>2){
    18             class D{
    19                 
    20             }
    21         }
    22         final class B{
    23             
    24         }
    25     }
    26     
    27     public void  sixi(final String s){
    28         int e=1;
    29         final int c=8;
    30         class C{
    31             /**
    32              * 在局部内部类或者匿名内部类中只能访问包含该内部类的范围(enclosing scope)的final变量。
    33              * 若不是则会报错。
    34              * 如int f=e;编译器报错。
    35              */
    36             String str=s;
    37             int d=c;
    38 //            int f=e;//编译器报错。
    39         }
    40     }
    41     public static void main(String[] args) {
    42         // TODO Auto-generated method stub
    43 
    44     }
    45 
    46 }

    匿名内部类:没有名字的内部类。

    下面的代码介绍了以下的内容:

    1.匿名内部类实现一个接口,

    2.匿名内部类实现一个没有默认构造方法的抽象类

    3.匿名内部类和局部内部类一样把参数定义成final,完成字段初始化

    4.匿名内部类用普通代码块{}完成初始化,弥补了匿名内部类没有构造方法的缺陷。

    代码如下:

    package com.qls.anonymouseInnerClass;
    /**
     * 匿名内部类(anonymous inner class)一般用在return 语句中。
     * 注意情况如下:
     * 匿名内部类由于没有名字,自然而然也就没有构造方法,其他三种内部类都有构造方法。
     * 没有构造方法怎么给对象赋值进行初始化呢?【答:用普通的代码块{},在这个代码块里面实行初始化。】
     * @author 秦林森
     *
     */
    interface B{
        void ouyangfeng();
    }
    abstract class C{
        private int i;
        public C(int i) {
            this.i=i;
        }
        public abstract int value();
        
    }
    public class A {
        public B getB(){
            //new B(){};就是匿名内部类:用默认的构造方法
            return new B() {
                
                @Override
                public void ouyangfeng() {
                    // TODO Auto-generated method stub
                    System.out.println("ouyangfeng is chief village of sixi ");
                }
            };
        }
        public C getC(final int i){
            //匿名内部类用一个带参数的构造方法
            return new C(i) {
                //用普通代码块实现初始化:
                {
                    //这里写两个输出语句作为演示。
                    System.out.println("泗溪");
                    System.out.println("ouyangfeng");
                    System.out.println(value());//输出value的值
                }
                @Override
                public int value() {
                    // TODO Auto-generated method stub
                    return i;//从这里可以看出要想引用i,必须把i定义成final。这和局部内部类一样。
                }
            };
            
        }
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            new A().getC(4);//输出泗溪、ouyangfeng、4
            
        }
    
    }

     嵌套内部类:

     1 package com.qls.nestedClass;
     2 /**
     3  * 如果你不想让内部类的对象和外部类的对象有如何联系的话,你就可以把内部类定义成static
     4  * 嵌套内部类(Nested inner class)的定义:类中关键词static修饰的内部类。
     5  * 注意情况如下:
     6  * 1.在嵌套内部类中不能访问外部类的非静态变量。
     7  * 2.创建内部类变量时,你不想通过创建外部类变量才能创建内部类变量时,你可以把这个内部类定义成static
     8  * 即嵌套内部类。
     9  * 3.在接口interface中定义的内部类默认都是public static 的,所以在接口中的内部类必是嵌套内部类。
    10  * @author 秦林森
    11  *
    12  */
    13 interface D{
    14     void hello();
    15     class Test implements D{
    16 
    17         @Override
    18         public void hello() {
    19             // TODO Auto-generated method stub
    20             System.out.println("hello");
    21         }
    22         public static void main(String[] args) {
    23             /**
    24              * 由于Test类默认是public static 的,所以创建Test对象时,不需要通过外部类D,
    25              * 所以直接new Test()即可创建Test类中的一个对象。
    26              * 话又说回来了,如果在接口中的类不是public static 的那么这个内部类也就是普通的内部类
    27              * 在创建Test的对象时,也就需要外部类的对象。关键D是接口,你怎么new 呢?
    28              * 所以在的类只能是static 的。
    29              */
    30             new Test().hello();//输出hello
    31         }
    32     }
    33 }
    34 public class A {
    35     int a=9;
    36     public static  class B{
    37 //        int b=a;编译报错
    38          void f(){
    39             System.out.println("f()");
    40         }
    41     }
    42     public static void main(String[] args) {
    43         /**
    44          * 从这里你看到了,可以对B直接new ,访问B中的函数f().
    45          * 但是如果B没有static这个关键字,即B是普通内部类时,必须这样才能访问到f()
    46          * new A().new B().f();
    47          */
    48         new B().f();
    49     }
    50 }

     二:比较一下局部内部类[local inner class]和匿名内部类【anonymous inner class ]的区别

    1.匿名内部类没有构造犯法,二局部内部类有构造方法。

    2.如果在一个外部类有两个或两个以上的方法,返回的都是某个接口或者抽象类的引用,建议把写一个局部内部类。若写成匿名内部类时,代码会显得特别冗长。反之如果一个时,建议用匿名内部类。

    代码如下:

     1 package com.qls.anonymouseInnerClass;
     2 interface Six{
     3     void six();
     4 }
     5 public class Ouyangfeng {
     6     private class SixTest implements Six{
     7 
     8         @Override
     9         public void six() {
    10             // TODO Auto-generated method stub
    11             
    12         }
    13         
    14     }
    15     public Six f(){
    16         return new SixTest();
    17     }
    18     public Six g(){
    19         return new SixTest();
    20     }
    21 }

    三:内部类的应用:

    用内部类实现java的多重继承。

     1 package com.qls.anonymouseInnerClass;
     2 class D{
     3     
     4 }
     5 abstract class E{
     6     
     7 }
     8 class F extends D{
     9     //这是实现多重继承的核心代码。这里是用一个匿名内部类实现
    10     E makeE(){
    11         return new E() {
    12         };
    13     }
    14 }
    15 public class MultipleInherit {
    16     public static void takesD(D d){
    17         
    18     }
    19     public static void takesE(E d){
    20         
    21     }
    22     public static void main(String[] args) {
    23         // TODO Auto-generated method stub
    24         F d = new F();
    25         takesD(d);
    26         takesE(d.makeE());
    27     }
    28 
    29 }

    最后简要介绍一下让一个类继承另一个类中的内部类?以及怎么让一个类中的内部类继承另一个类的内部类呢?

    首先是:让一个类继承另一个类中的内部类

     代码如下:

     1 package com.qls.anonymouseInnerClass;
     2 
     3 import com.qls.anonymouseInnerClass.WithInner.Inner;
     4 
     5 class WithInner{
     6     class Inner{
     7         private int a;
     8         public Inner(int a) {
     9             this.a=a;
    10         }
    11         public Inner() {
    12             // TODO Auto-generated constructor stub
    13         }
    14     }
    15 }
    16 public class InheritInner extends Inner{
    17     public InheritInner(WithInner withInner) {
    18         // TODO Auto-generated constructor stub
    19         /**
    20          * 这句话必须要写。否则编译器会报错。即:外部类的一个对象.super().
    21          * 这里的super(),比奥斯Inner的一个默认构造方法。
    22          * 如果Inner中比如有这样一个构造方法:public Inner(int a) 
    23          * 你现在也可以写成:把withInner.super();改为withInner.super(1);编译器是不会报错的。
    24          * 如果没有默认构造方法public Inner() 则这题必须写成:withInner.super(1);的形式。
    25          */
    26         
    27         withInner.super();
    28     }
    29     public static void main(String[] args) {
    30         // TODO Auto-generated method stub
    31         WithInner withInner = new WithInner();
    32         InheritInner inheritInner = new InheritInner(withInner);
    33     }
    34 
    35 }

     让一个类中的内部类继承另一个类的内部类

    代码如下:

     1 package com.qls.anonymouseInnerClass;
     2 /**
     3  * 朱元璋家住凤阳,刘伯温家住青田
     4  * @author 秦林森
     5  *
     6  */
     7 class ZhuYuanZhang{
     8     class FengYang{
     9         private String location;
    10 
    11         public FengYang(String location) {
    12             this.location = location;
    13         }
    14         
    15     }
    16 }
    17 class LiuBoWei{
    18     class QingTian extends ZhuYuanZhang.FengYang{
    19         private String location;
    20         public QingTian(ZhuYuanZhang zhuYuanZhang, String location) {
    21             zhuYuanZhang.super(location);//这句话必须要写。或者会报错,
    22             this.location=location;
    23         }
    24         public void accurate(){
    25             System.out.println("一统江山刘伯温 ,家在"+location);
    26         }
    27     }
    28 }
    29 public class Test {
    30 
    31     public static void main(String[] args) {
    32         // TODO Auto-generated method stub
    33         new LiuBoWei().new QingTian(new ZhuYuanZhang(), "青田").accurate();
    34     }
    35 
    36 }/*Output:
    37 一统江山刘伯温 ,家在青田*///:~
  • 相关阅读:
    省队集训 Day1 残缺的字符串
    省队集训 Day3 吴清华
    省队集训 Day3 陈姚班
    Java多线程中的join方法
    Java多线程同步机制之同步块(方法)——synchronized
    java-实用的sql语句
    java-分页之页面分页
    java下实现调用oracle的存储过程和函数
    java-MySQL存储过程
    MySQL存储过程
  • 原文地址:https://www.cnblogs.com/1540340840qls/p/6237919.html
Copyright © 2020-2023  润新知