thinking in java (六) ----- 内部类(一,Inner classes)

将某个class定义置于另一个class定义之中是可行的,这就是内部类。

内部类基础

内部类一般来说包括以下几种:成员内部类,局部内部类,匿名内部类,静态内部类。

  • 成员内部类

成员内部类是最普通的内部类,定义在一个外部类的内部,如下:

class Circle {
    double radius = 0;
     
    public Circle(double radius) {
        this.radius = radius;
    }
     
    class Draw {     //内部类
        public void drawSahpe() {
            System.out.println("drawshape");
        }
    }
}

看起来Draw就像是Circle的一个成员,Circle是外部类。成员内部类可以无条件访问外部类的成员属性和成员方法(包括私有和静态成员),如下:

class Circle {
    private double radius = 0;
    public static int count =1;
    public Circle(double radius) {
        this.radius = radius;
    }
     
    class Draw {     //内部类
        public void drawSahpe() {
            System.out.println(radius);  //外部类的private成员
            System.out.println(count);   //外部类的静态成员
        }
    }
}

不过需要注意的是,如果内部类里面有和外部类同名的成员变量或者方法时,默认的是访问成员内部类的成员,如果要访问外部类的成员,需要用一下形式访问:

外部类.this.成员变量
外部类.this.成员方法

虽然成员内部类可以无条件访问外部类的成员,但是外部类想要访问成员内部类的成员就没有这么随心所欲了。在外部类中如果要访问成员内部类的成员,必须先创建一个内部类对象,在调用这个对象的引用来访问:一般都会申明一个方法,返回一个reference指向内部类。

class Circle {
    private double radius = 0;
 
    public Circle(double radius) {
        this.radius = radius;
        getDrawInstance().drawSahpe();   //必须先创建成员内部类的对象,再进行访问
    }
     
    private Draw getDrawInstance() {
        return new Draw();
    }
     
    class Draw {     //内部类
        public void drawSahpe() {
            System.out.println(radius);  //外部类的private成员
        }
    }
}

成员内部类是依靠于外部类存在的,如果要创建内部类对象,必须现有外部类对象。创建成员内部类对象的一般方式如下

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() {
             
        }
    }
}

成员内部了可以有private protected public访问权限。如果成员内部类使用private修饰,则只能在外部类的内部访问。如果使用public访问,则任何地方可以访问,如果protected修饰,在同一个包下或者继承了外部类的情况下访问。外部类就不能用private修饰。

  • 局部内部类

局部内部类是定义在一个method,或者是一个scope里面的类,他和成员内部类的区别在于:局部内部类的访问权限仅限于作用method和作用scope中

定义在方法中:

class People{
    public People() {
         
    }
}
 
class Man{
    public Man(){
         
    }
     
    public People getWoman(){
        class Woman extends People{   //局部内部类
            int age =0;
        }
        return new Woman();
    }
}

定义在作用域中:

public class Parcel6 {
    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("chenssy");
            String string = ts.getSlip();
        }
    }
    
    public void track(){
        internalTracking(true);
    }
    
    public static void main(String[] args) {
        Parcel6 parcel6 = new Parcel6();
        parcel6.track();
    }
}

局部内部类就像是一个局部变量一样,所以是没有private public protected等修饰符的。

  • 匿名内部类

匿名内部类是我们比较常见的,在编写事件监听的代码时候,使用匿名内部类不仅方便,而且代码更容易维护,下面这段代码是Android事件 监听代码。

scan_bt.setOnClickListener(new OnClickListener() {
             
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                 
            }
        });
         
        history_bt.setOnClickListener(new OnClickListener() {
             
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                 
            }
        });

这段代码是为两个按钮设置监听器,这里面就使用了匿名内部类,这段代码中:

new OnClickListener() {
             
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                 
            }
        }

代码中需要给按钮设置监听器对象,所以匿名内部类能够在实现父类或者接口方法情况下,同时产生一个相应的对象,但是前提是这个父类或者接口实现存在。当然像下面这种方法也是一样的效果。

private void setListener()
{
    scan_bt.setOnClickListener(new Listener1());       
    history_bt.setOnClickListener(new Listener2());
}
 
class Listener1 implements View.OnClickListener{
    @Override
    public void onClick(View v) {
    // TODO Auto-generated method stub
             
    }
}
 
class Listener2 implements View.OnClickListener{
    @Override
    public void onClick(View v) {
    // TODO Auto-generated method stub
             
    }
}

这样的代码荣长也难以维护,所以一般匿名内部类的方法用来编写事件监听的代码,同样的匿名内部类也是不能有访问修饰符修饰。

匿名内部类是唯一没有构造器的类,正是因为没有构造器,所以匿名内部类的范围比较有限,大部分匿名内部类用于接口回调,一般来说,匿名内部类适用于继承其他类或者实现接口,并不需要增加额外的方法,只是对继承方法或者接口的重写或者实现。

  • 静态内部类

静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法,这点很好理解,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体的对象。

参考博文:http://www.cnblogs.com/dolphin0520/p/3811445.html

猜你喜欢

转载自blog.csdn.net/sinat_38430122/article/details/83151050