【学习笔记】 唐大仕—Java程序设计 第5讲 深入理解Java语言之5.5 内部类与匿名类

/**
* 内部类与匿名类
* @author cnRicky
* @date 2018.11.10
*/
内部类与匿名类
  • 内部类(inner class)是在其他类中的类
  • 匿名类(anonymous class)是一种特殊的内部类,它没有类名
内部类(Inner class)
  • 内部类的定义

    • 将类的定义class xxxx{...}置入一个类的内部即可
    • 编译器生成xxxx$xxxx这样的class文件
    • 内部类不能够与外部类同名
  • 内部类的使用

    • 在封装它的内的内部使用内部类,与普通的使用方式相同
    • 在其他地方使用
      • 类名前要冠以外部类的名字
      • 在用new创建内部类时,也要在new前面冠以对象变量
      • 外部对象名.new 内部类名(参数)
class TestInnerClass{
    public static void main( String[] args ){
        Parcel p = new Parcel();
        p.testShip();

        Parcel.Contents c = p.new Contents(33);
        Parcel.Destination d = p.new Destination( "Hawii" );
        p.setProperty( c, d );
        p.ship();
    }
}

class Parcel {
  private Contents c;
  private Destination d;
  class Contents {
    private int i;
    Contents( int i ){ this.i = i; }
    int value() { return i; }
  }
  class Destination {
    private String label;
    Destination(String whereTo) {label = whereTo;}
    String readLabel() { return label; }
  }
  void setProperty( Contents c, Destination d ){
    this.c =c; this.d = d;
  }
  void ship(){
    System.out.println( "move "+ c.value() +" to "+ d.readLabel() );
  }
  public void testShip() {
    c = new Contents(22);
    d = new Destination("Beijing");
    ship();
  }
}

 

在内部类中使用外部类的成员
  • 内部类中可以直接访问外部类的字段及方法

    • 即使private也可以
  • 如果内部类中有与外部类同名的字段或方法,则可以用

    • 外部类名.this.字段及方法
  • 例子:

class A
{
    private int s = 111;
    
    public class B{
        private int s = 222;
        public void mb(int s){
            System.out.println(s);//局部变量s
            System.out.println(this.s);//内部类对象的属性s
            System.out.println(A.this.s);//外层类对象属性s
        }
    }
}

 

内部类的修饰符
  • 内部类与类中的字段、方法一样是外部类的成员,它的前面也可以有访问控制符和其他修饰符
    • 访问控制符:public、protected,默认(default)及private
      • 注:外部类只能够使用public修饰或者默认
    • final,abstract
static修饰符
  • 用static修饰内部类,表名该内部类实际是一种外部类

    • 因为它与外部类的实例无关
    • 有人认为static的类是嵌套类(nested class),不是内部类(inner class)
  • static类在使用时:

    • 1、实例化static类时,在new前面不需要用对象实例变量;
    • 2、static类中不能访问其外部类的非static的字段及方法,即只能够访问static成员
    • 3、static方法中不能访问非static的域及方法,也不能够不带前缀地new一个非static的内部类
  • 例子:

public class TestInnerStatic
{
    public static void main(String[] args)
    {
        A.B a_b = new A().new B();//ok
        A a = new A();
        A.B ab = a.new B();
        
        Outer.Inner oi = new Outer.Inner();
        //Outer.Inner oi2 = new Outer.new Inner();//!!!error
        //Outer.Inner oi3 = new Outer().new Inner();//!!!error
    }
}

class A
{
    private int x;
    void m(){
        new B();
    }
    static void sm(){
        //new B();//error!!!
    }
    class B
    {
        B(){ x = 5; }
    }
}
class Outer
{
    static class Inner
    {
        
    }
}

 

局部类
  • 在一个方法中也可以定义类,这种类称为“方法中的内部类”
  • 或者叫局部类(local class)
  • 例子:
class TestInnerInMethod
{
    public static void main(String[] args)
    {
        Object obj = new Outer().makeTheInner(47);
        System.out.println("Hello World!" + obj.toString());
    }
}

class Outer
{
    private int size = 5;
    public Object makeTheInner(int localVar)
    {
        final int finalLocalVar = 99;
        class Inner{
            public String toString(){
                return("InnerSize:" + size +
                      // "localVar:" + localVar + //Error!
                       "finalLocalVar:" + finalLocalVar
                      );
            }
        }
        return new Inner();
    }
}

 

使用局部类
  • 1、同局部变量一样,方法中的内部类

    • 不能够用public,private,protected,static修饰
    • 但可以被final或者abstract修饰
  • 2、可以访问其外部类的成员

  • 3、不能够访问该方法的局部变量,除非是final局部变量

匿名类
  • 匿名类(anonymous class)是一种特殊的内部类

    • 它没有类名,在定义类的同时就生成该对象的一个实例
    • “一次性使用”的类
  • 例子:

class TestInnerAnonymous
{
    public static void main(String[] args) 
    {
        
    }
}

class Outer
{
    private int size = 5;
    public Object makeTheInner(int localVar)
    {
        final int finalLocalVar = 99;
        return new Object(){
            public String toString(){
                return ("InnerSize:" + size + "finalLocalVar:" + finalLocalVar);
            }
        };
    }
}

 

匿名类的使用
  • 1、不取名字,直接用其父类或接口的名字

    • 也就是说,该类是父类的子类,或者实现了一个接口
    • 编译器生成xxxxx$之类的名字
  • 2、类的定义的同时就创建实例,即类的定义前面有一个new

    • new 类名或接口名(){ ...... }
    • 不使用关键字class,也不使用extends及implements
  • 3、在构造对象时使用父类构造方法

    • 不能够定义匿名类的构造方法,因为它没有名字
    • 如果new对象时,要带参数,则使用父类的构造方法
匿名类的应用
  • 用到界面的事件处理
    • 注册一个事件监听器
    • 示例AutoScore.java中
//SymAction ISymAction = new SymAction();
//btnNew.addActionListener(ISymAction);

btnNew.addActionListener(new ActionListener(){
   public void actionPerformed(ActionEvent event)
   {
       ......;
   }
});

 

  • 作为方法的参数
    • 排序,给一个比较大小的接口
    • 如:
Arrays.<Book>sort(books, new Comparator<Book>(){
    public int compare(Book b1, Book b1){
        return b1.getPrice()-b2.getPrice();
    } 
});

 

posted @ 2018-11-10 20:44  cnRicky  阅读(417)  评论(0编辑  收藏  举报