java

java 内部类

2018-05-10  本文已影响2人  n油炸小朋友

内部类分为以下四种:

一、静态内部类

public class OuterClass {//外部类
   
    public int aa; //普通成员变量
    private static float f = 1.5f;//private的静态成员
    
    static void myPrintln() {
        System.out.println("静态方法");
    }
    
    protected static class StaticInnerClass{//protected的静态内部类
        
        float a;
        
        public StaticInnerClass() {
             a = f;// 外围类的private静态变量
             myPrintln();//外围类的静态方法
        }
    }
}

class OtherClass{

   public static void main(String[] args) {
       //创建静态内部类的对象
    OuterClass.StaticInnerClass staticInnerClass = new OuterClass.StaticInnerClass(); 
   } 
}

二、成员内部类

成员内部类中的 this关键字:
成员内部类访问外部类成员

当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,默认情况下访问的是成员内部类的成员。

如果要访问外部类的同名成员,需要以下面的形式进行访问:

  - 外部类.this.成员变量
  - 外部类.this.成员方法
外部类访问成员内部类的成员
1.先创建一个成员内部类的对象
2.再通过指向这个对象的引用来访问。
创建成员内部类对象的一般方式:

在外部类的成员方法中创建成员内部类 (内部类名 对象名=new 内部类名();)与 在其他类中或静态方法中创建成员内部的方式是不一样的

public class Test {
    public static void main(String[] args)  {
        //第一种方式:
        Outter outter = new Outter();
        Outter.Inner inner = outter.new Inner();  //必须通过Outter对象来创建
         
        //第二种方式:
        Outter.Inner inner1 = outter.getInnerInstance();
    }
}
 ///////////////////////////////////////////////////////////////////////////////
class Outter {
    private Inner inner = null;
    public Outter() {
         
    }
     
    public Inner getInnerInstance() {
        if(inner == null)
            inner = new Inner();
        return inner;
    }
      
    class Inner {
        public Inner() {
             
        }
    }
}

上面的例子,如果成员内部类Inner用private修饰,则只能在外部类的内部访问,如果用public修饰,则任何地方都能访问;如果用protected修饰,则只能在同一个包下或者继承外部类的情况下访问;如果是默认访问权限,则只能在同一个包下访问。这一点和外部类有一点不一样,外部类只能被public和包访问两种权限修饰。我个人是这么理解的,由于成员内部类看起来像是外部类的一个成员,所以可以像类的成员一样拥有多种权限修饰。

成员内部类被继承

在内部类的访问权限允许的情况下,成员内部类也是可以被继承的。由于成员内部类的对象依赖于外围类的对象。因此,继承了成员内部类的子类必须要与一个外围类对象关联起来。同时,子类的构造器是必须要调用父类的构造器方法,所以也只能通过父类的外围类对象来调用父类构造器。


class ChildClass extends OuterClass.InnerClass{
    
    //成员内部类的子类的构造器的格式
    public ChildClass(OuterClass outerClass) {
        outerClass.super();//通过外围类的对象调用父类的构造方法
    }
}

三、局部内部类

public class OuterClass {
    
    private int a = 21;
    
    static {//静态域中的局部内部类
       class LocalClass1{
              //  int z = a; //错误,在静态的作用域中无法访问对象成员
       }
    }
    
    {//实例初始化块中的局部内部类
        class localClass2{          
        }
    }
    
    public OuterClass(){
        int x = 2;
        final int y = 3;
        // x = 3;//若放开此行注释,编译无法通过,因为局部变量x已经是final类型
        //构造器中的局部内部类
        class localClass3{
            int z = y; //可以访问final的局部变量
            int b = a;//可以访问类的所有成员
             //访问没有用final修饰的局部变量
            int c = x;
        }
    }
    
    public void createRunnable() {
        
        final int x = 4;
        //方法中的局部内部类
        class LocalClass4 implements Runnable {//
            @Override
            public void run() {
                System.out.println("局部final变量:"+x);
                System.out.println("对象成员变量:"+a);
            }
            
        }
    }
}

四、匿名内部类

作用:

匿名内部类用于隐式继承某个类(重写里面的方法或实现抽象方法)或者实现某个接口。

匿名内部类的访问限制:

在实例环境中(构造器、对象成员方法、实例初始化块),则可以访问外围类的所有成员;但如果内部类定义在静态环境中(静态初始化块、静态方法),则只能访问外围类的静态成员

匿名内部类的优缺点:

一个例子:

class MyOuterClass {

    private int x = 5;

    void createThread() {
        
        final int a = 10;
        int b = 189;
        
        // 匿名内部类继承Thread类,并重写Run方法
        Thread thread = new Thread("thread-1") {

            int c = x;  //访问成员变量
            int d = a;  //final的局部变量
            int e = b; //访问没有用final修饰的局部变量
            
            @Override
            public void run() {
                System.out.println("这是线程thread-1");
            }
        };

        // 匿名内部类实现Runnable接口
        Runnable r = new Runnable() {

            @Override
            public void run() {
                System.out.println("线程运行中");
            }
        };
    }
}

内部类嵌套内部类

class InnerClass{//成员内部类
        private double aa; //与围类的变量aa的名字重复
        
        public InnerClass(){
            this.aa = OuterClass.this.aa + f;//明确指定两个aa的所属
            initInnerClass();
        }
        
        public  class InnerInnerCalss2{//成员内部类中的成员内部类
            protected double aa = OuterClass.this.aa;//最外层的外围类的成员变量
        }//InnerInnerCalss2
    }//InnerClass

总结

类 型 访问修饰符 声明静态成员 绑定外围类
静态内部类 四种访问修饰符 可以声明 不绑定
成员内部类 四种访问修饰符 除 final static 的变量外,其余静态成员都不行 绑定
局部内部类 不可以声明 不可以声明 取决于此内部类的声明环境
局部内部类 不可以声明 不可以声明 取决于此内部类的声明环境
为什么在Java中需要内部类

1. 每个内部类都能独立的继承一个接口的实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。内部类使得多继承的解决方案变得完整,

2. 方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏。

3. 方便编写事件驱动程序

4. 方便编写线程代码

上一篇下一篇

猜你喜欢

热点阅读