你的位置:首页 > Java教程

[Java教程]基础学习day09

一、内部类

 

1.1、内部类概念

定义在一个类内部中的另一个类,被称为内部类

特点:

可以直接访问,内部类的外部类中的,成员属性和方法(包含-private)

外部类要访问内部类中的成员和方法,需要先建立内部类对象

1.2、示例

 

package com.day08.innerclass.demo1;/** * 包含内部类 * @author denny * */public class Outer { //外部类    //private成员  private String name="张三";  private int age=20;  private String gender="男";    /**   * 内部类   */  class Inner{    private int num=3;        public void hello(){      System.out.println("姓名:"+name+"年龄:"+age          +"性别:"+gender);    }    public int getNum() {      return num;    }    public void setNum(int num) {      this.num = num;    }          }        /*   * 外部类中的方法   */  public void show(){    System.out.println("姓名:"+this.name+"年龄:"+this.age        +"性别:"+this.gender);  }    /*   * 调用内部类   */  public void say(){    Inner inner=new Inner();    System.out.println("调用内部类:"+"num="+inner.getNum()+", num="+inner.num);  }  public String getName() {    return name;  }  public void setName(String name) {    this.name = name;  }  public int getAge() {    return age;  }  public void setAge(int age) {    this.age = age;  }  public String getGender() {    return gender;  }  public void setGender(String gender) {    this.gender = gender;  }  }

 

测试外部类

package com.day08.innerclass.demo1;public class OuterTest {  public static void main(String[] args) {    //外部类调用内部类    Outer o=new Outer();    o.show();    o.say();  }}

结果:

姓名:张三年龄:20性别:男
调用内部类:num=3, num=3

测试内部类

package com.day08.innerclass.demo1;public class InnerTest1 {  public static void main(String[] args) {    // 声明内部类中对 象,先声明外部类,再声明内部类    Outer.Inner inner = new Outer().new Inner();    inner.hello();  }}

姓名:张三年龄:20性别:男
调用内部类:num=3, num=3

1.3、静态内部类

如果内部类是static修饰的就只能调用父类中static成员

声明方式,可直接外部类.内部类()来声明或者调用

 

package com.day08.innerclass.demo3;public class Outer {  //private成员    private String name="张三";    static int age=20;    private String gender="男";        /*     * 外部类中的方法     */    public void show(){      System.out.println("姓名:"+this.name+"年龄:"+this.age          +"性别:"+this.gender);    }    /**     * 内部类     */    static class Inner{      private int num=3;            public void hello(){        System.out.println("外部类年龄:"+age            +",内部类属性"+this.num);      }      }    public static void main(String[] args) {      //静态内部类可以直接通过外部类.内部类声明      Outer.Inner inner=new Outer.Inner();      inner.hello();    }}

 

外部类年龄:20,内部类属性3

1.4、内部类成员是static的话

这个内部类必须被static修饰,static只能调用外部类和内部类中的stiatic的成员.

 

package com.day08.innerclass.demo3;public class Outer {  //private成员    private String name="张三";    static int age=20;    private String gender="男";        /*     * 外部类中的方法     */    public void show(){      System.out.println("姓名:"+this.name+"年龄:"+this.age          +"性别:"+this.gender);    }    /**     * 内部类     */     static class Inner{      private static int num=3;            public static void hello(){        System.out.println("外部类年龄:"+age            +",内部类属性"+num);      }      }    public static void main(String[] args) {      //静态内部类m成员也是静态的可以直接调用      Outer.Inner.hello();    }}

 

结果:外部类年龄:20,内部类属性3

1.5、声明在外部类中成员方法中的内部类

声明成员方法中的,内部类,调用成员方法中的局部变量 时,成员方法中的局部变量 必须为final修饰

package com.day08.innerclass.demo3;public class Outer {  // private成员  private String name = "张三";  static int age = 20;  private String gender = "男";  /*   * 外部类中的方法   */  public void show(int x) {    final int y = 5;    //System.out.println("姓名:" + this.name + "年龄:" + this.age + "性别:" + this.gender);    class Inner {      public void hello() {        System.out.println("hello-------"+x + " ," + y);      }    }    Inner inner = new Inner();    inner.hello();  }  /**   * 内部类   */  public static void main(String[] args) {    //声明成员方法中的,内部类,调用成员方法中的局部变量 时,成员方法中的局部变量 必须为final修饰    new Outer().show(8);  }}

hello-------8 ,5

 

 

1.6、为什么内部类能直接访问外部类中的成员呢?

因为内部类持有了外部类的引用,外部类名.this。  (默认省略)
package com.day08.innerclass.demo4;public class Outer {  private int num=3;    class Inner{    private int num=4;        public void show(){      int num=5;      //局部变量      System.out.println(num);      //内部类的成员变量      System.out.println(this.num);      //外部类的成员变量       System.out.println(Outer.this.num);    }  }  public static void main(String [] args){    new Outer().new Inner().show();  }}

二、匿名内部类


2.1、匿名内部类概念 

内部类可以继承或实现一个外部类或者接口。

格式:
    new 外部类名或者接口名(){覆盖类或者接口中的代码,(也可以自定义内容。)}
    简单理解:
    就是建立一个带内容的外部类或者接口的子类匿名对象。
    什么时候使用匿名内部类呢?
    通常使用方法是接口类型参数,并且该接口中的方法不超过三个,可以将匿名内部类作为参数传递。
    好处:
    增强阅读性。

2.2、重写类中的方法

 

package com.day08.innerclass.demo5;/** * 抽象类 * @author denny * */public abstract class Person {    private String name="张三";    public void show(){    System.out.println(this.name);      }  public String getName() {    return name;  }  public void setName(String name) {    this.name = name;  }  }

 

 

package com.day08.innerclass.demo5;/** * 外部类 * * @author denny 实现有一个方法的抽象类的匿名内部类 * */public class Outer {  private int num = 3;  public void say() {    new Person() {// 匿名内部类      public void show() { //重写抽象类中的方法,抽象方法,普通方法都可以        System.out.println("..............." + num);      }    }.show(); //对象创建完成,调用自己  }  public static void main(String[] args) {    new Outer().say();  }}

 

结果:

...............3

第二种写法,适后重写了多个方法

package com.day08.innerclass.demo5;/** * 外部类 * * @author denny 实现有一个方法的抽象类的匿名内部类 * */public class Outer {  private int num = 3;  public void say() {    Person person=new Person() {// 匿名内部类      public void show() { //重写抽象类中的方法,抽象方法,普通方法都可以        System.out.println("..............." + num);      }    };    //对象创建完成    person.show();  }  public static void main(String[] args) {    new Outer().say();  }}

2.3、示例使用接口的方式

package com.day08.innerclass.demo6;/** * 接口 * @author denny * */public interface BirdPro {    /**   * 2个抽象方法   */  public void shout();    public void accact();}package com.day08.innerclass.demo6;public class Outer {  private String name="张三";    public void show(){    int y=3;    BirdPro birdPro=new BirdPro(){      //实现接口中的方法      @Override      public void shout() {        System.out.println(name+","+y);              }      @Override      public void accact() {        System.out.println(y+","+name);              }                };    birdPro.shout();    birdPro.accact();  }    public String getName() {    return name;  }  public void setName(String name) {    this.name = name;  }  public static void main(String[] args) {    new Outer().show();  }}

结果:

张三,3
3,张三

2.4、把匿名内部类做参数传递

  1. 通常的使用场景之一:
  2. 当函数参数是接口类型时,而且接口中的方法不超过三个。
  3. 可以用匿名内部类作为实际参数进行传递。

 

 

package com.day08.innerclass.demo6;/** * 接口 * * @author denny * */public interface BirdPro {  /**   * 2个抽象方法   */  public void shout();  public void accact();}

 

package com.day08.innerclass.demo6;class InnerDemo {  public static void main(String[] args) {    // 把接口做参数传递    show(new BirdPro() {      // 实现接口中的方法      @Override      public void shout() {        System.out.println("叫声");      }      @Override      public void accact() {        System.out.println("攻击");      }    });  }  public static void show(BirdPro birdPro) {// 做参数    // 调用    birdPro.accact();    birdPro.shout();  }}

 

2.5、 初始化顺序

package com.day08.innerclass.demo2;public class Fu {  int num = 9;  static{    System.out.println(" static Fu");  }  {    System.out.println("Fu");  }  Fu() {    super();// Object    // 显示初始化    // 构造代码块初始化    show(); // 构造函数调用方法,如果子类已经重写了,父类的方法,则执行子类的方法,但这时,成员还没有初初始化,所以为默认值  }  void show() {    System.out.println("fu show " + num);// 被覆盖,运行子类的  }}

package com.day08.innerclass.demo2;public class Zi extends Fu {  int num = 8;  static{    System.out.println(" static Zi");  }  {     System.out.println("Zi" );  }  Zi(){      super();      //显示初始化      //构造代码块初始化     show();  }   void show(){     System.out.println("zi show " + num);   }}

package com.day08.innerclass.demo2;public class Test1 {  public static void main(String[] args) {    new Zi();  }}

结果:

static Fu static ZiFuzi show 0Zizi show 8