12.1内部类

(笔记:当一个类只需要在一个类中使用而与其他类无关时,就可以将这个类写在使用这个类的内部,这就是内部类的使用场合)

内部类是指在一个外部类的内部再定义一个类。类名不需要和文件名相同。

内部类可以是静态static的,也可用public,default,protected和private修饰。(而外部顶级类即类名和文件名相同的只能使用public和default)。

注意:内部类是一个编译时的概念,一旦编译成功,就会成为完全不同的两类。对于一个名为Outer的外部类和其内部定义的名为Inner的内部类。编译完成后出现Outer.class和Outer$Inner.class两类。所以内部类的成员变量/方法名可以和外部类的相同。

12.1.1成员内部类

1.成员内部类,就是作为外部类的成员,可以直接使用外部类的所有成员属性和方法,即使是private的。同时外部类要访问内部类的所有成员变量/方法,则需要通过内部类的对象来获取。

2.要注意的是,成员内部类不能含有static的变量和方法。因为成员内部类需要先创建了外部类对象,才能创建它自己的。

  1. 在成员内部类要引用外部类对象时,使用Outer.this来表示外部类对象;

(当内部类与外部类有相同的属性/方法的时候,要特指使用外部类的属性和方法时:外部类名.this.属性名/方法名

4.而需要创建内部类对象时,可以使用:

Outer.Inner inner = outerobj.new Inner();(外部类名.内部类名 对象引用名= 外部类对象引用名.new 内部名()

一般只在外部类中使用,不在外部使用内部类

public class Outer { 
  /**
  *只有Outer的对象才有Inner内部类存在,即成员内部类是属于外部类的对象的
  */
    public class Inner {//成员内部类
        public void print(String str) { 
            System.out.println(str); 
        } 
    } 
}
    public static void main(String[] args) { 
        Outer outer = new Outer(); 
        Outer.Inner inner = outer.new Inner(); //创建成员内部类对象
        inner.print("Outer.new"); 
    }

12.1.2静态内部类(嵌套内部类)

​ 1.静态内部类(嵌套内部类),就是修饰为static的内部类。声明为static的内部类,不需要内部类对象和外部类对象之间的联系,就是说我们可以直接引用Outer.Inner,即不需要创建外部类对象,也不需要创建内部类。

2.静态内部类和普通的内部类还有一个区别:普通内部类不能有static数据和static属性,也不能包含嵌套类(静态类),但静态内部类可以。而静态内部类不建议声明为private,一般声明为public,方便调用。

​ 3.静态内部类的内部 不能访问外部类的非静态成员

12.1.3 匿名内部类

有时候我们为了免去给内部类命名,便倾向于使用匿名内部类,因为它没有名字。

匿名内部类可以定义在方法中和外部类中当作成员变量的值,此时成员变量为匿名内部类父类的引用,可以为静态成员

匿名内部类是不能加访问修饰符的。要注意的是,new 匿名类,这个类是要先定义的,看下面例子:

public class Main{
  public static void main(String [] args){
    final int i = 10; 
  //匿名内部类的匿名对象(因为匿名内部类是通过new实现的,所以整体是一个对象(匿名类对象))
    new Random(){
      int a;
      public void test(){
        //在匿名内部类中使用局部变量,必须是final修饰的(jdk1.8可以省略final不会报错)
        System.out.print(i);//不能修改局部变量i
      }
    };   
  }
}
public class Outer { 
    public static void main(String[] args) { 
        Outer outer = new Outer(); 
        Inner inner = outer.getInner("Inner", "gz"); 
        System.out.println(inner.getName()); 
    }

    public Inner getInner(final String name, String city) { 
        return new Inner() { 
            private String nameStr = name; 

            public String getName() { 
                return nameStr; 
            } 
        }; 
    }
}

//注释后,编译时提示类Inner找不到,即匿名内部类的父类一定要先存在 
/* interface Inner { 
    String getName(); 
} */

注意:在这个例子,留意外部类的方法的形参,当所在的方法的形参需要被内部类里面使用时,该形参必须为final。因为,为了避免引用值发生改变,例如被外部类的方法修改等,而导致内部类得到的值不一致,于是用final来让该引用不可改变。

//接口与匿名内部类结合使用的实例:模拟办公室通过监控器来监控工地工人搬砖的情况,思路:
1.建一个Office类  
2.建一个工地类  
3.肯定要用到监控,但监控器可以来自不同的厂家,所以要定义监控器的功能,厂家生产的监控器只要满足工地监控器的功能即可使用,
所以定义一个OncameraListenner接口,即监控器的标准   
4.因为要监控工地,所以要在工地装好监控器,即在工地类中定义一个监控器listenner成员,去调用监控器的各种功能,
同时给工地监控一个设置使用哪家监控器的方法setListenner(OncameraListenner listenner)   
5.最后,在办公室要打开监控时需要指定到底使用哪家厂商的监控器,调用setListenner()方法时指定使用哪家厂商的监控器,
即传入OncameraListenner接口的实现类对象,这里为了展现匿名类的应用,所以使用了匿名内部类来实现接口。

/**
 * 工厂搬砖与办公室信息传输协议
 * @author Administrator
 *
 */
public interface OncameraListenner {

    /**
     * 可以通知办公室开始搬砖的信息
     */
    void start();

    /**
     * 可以通知办公室搬砖过程的信息
     */
    void progress(String name, int progress, String from, String to);

    /**
     * 可以通知办公室结束搬砖的信息
     */
    void stop();
}


/**
 * 工地
 * @author Administrator
 *
 */
public class ConstructionSite {

    private OncameraListenner listenner;

    public void setListenner(OncameraListenner listenner){
        this.listenner=listenner;
    }

    public void banzhuan(String name,int sum){
        /**
         * 开始搬砖
         */
        if(listenner!=null){
            listenner.start();
        }
        //模拟耗时操作
        for (int i = 1; i <= sum; i++) {
            /**
             * 搬砖的进度
             */
            if(listenner!=null){
                listenner.progress(name, i, "澳大利亚", "深圳");
            }
        }
        /**
         * 搬砖结束
         */
        if(listenner!=null){
            listenner.stop();
        }
    }
}



/**
 * 办公室
 * @author Administrator
 *
 */
public class Office {
    /**
     * 希望在这里打印搬砖的信息
     * @param args
     */
    public static void main(String[] args) {
        ConstructionSite cs = new ConstructionSite();

        //给工厂装监控器(接口回调)
        cs.setListenner(new OncameraListenner() {

            @Override
            public void stop() {
                System.out.println("结束搬砖啦");
            }

            @Override
            public void start() {
                System.out.println("开始搬砖啦");
            }

            @Override
            public void progress(String name, int progress, String from, String to) {
                System.out.println(name+"从"+from+"搬砖到"+to+",进度为:"+progress);
            }
        });

        //指挥张三开始搬砖
        cs.banzhuan("张三", 100);
    }    
}

results matching ""

    No results matching ""