Java学习-内部类

一、基本含义

1.1 含义

将类1放在类2的内部,类1叫做内部类,类2叫做类1外部类。

1.2 作用

(1)封装性更强。除了outer类,其他类都不能访问(包含同包其它类)。
(2)inner类可以访问outer类所有成员(包含私有成员)。反之,不可。
(3)便捷性。inner类实现的功能,使用outer类也可实现,只是有时不方便。

二、内部类成员

2.1 成员内部类——普通inner类+ 静态inner类

2.1.1 含义

是outer类的一个成员。
普通内部类:修饰词为public。

public class OuterClass {
  // 成员内部类。即普通内部类。
  public class InnerClass{    
    name = "张三";
    age = 18;
    public InnerClass(){
    } 
  }  
}

静态内部类:修饰词为public + static。

public class OuterClass {
  // 静态内部类。
  public static class InnerClass{    
    name = "张三";
    age = 18;
    public InnerClass(){
    } 
  }  
}

2.1.2 使用

public class OuterClass {
  private String name;
  private int age;
  public int age() {
    return age;
  }
  public int getAge() {
    return age;
  }
  public void setAge(int age) {
    this.age = age;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public void outerShow1() {
    System.out.println("外部类方法");
  }
  public OuterClass() {
  }
  public OuterClass(String name, int age) {
    this.name = name;
    this.age = age;
  }
  // 普通内部类。可以直接访问outer类的成员。
  public class InnerClass {
    String name = "李四";
    public InnerClass() {
      age = 18; // 普通内部类可以直接使用outer类的属性
    }
    public void show() {
      System.out.println("姓名1:" + getName() + ";年龄:" + getAge()); // age和getAge()效果等价。
      System.out.println("姓名2:" + name + ";年龄:" + age); // 属性调用:就近原则。
      System.out.println("姓名3:" + OuterClass.this.name + ";年龄:" + age);// getName()和OuterClass.this.name效果等价。
   }
  }
  // 静态内部类。不可以直接访问非静态成员。
  public static class InnerClass2 {
    String name = "李四";
    public InnerClass2() {
    }
    public void show() {
      System.out.println("外部类name=" + new OuterClass().name + ",内部类name=" + name);
    }
  }
  // 方法内部类。
  public void showInnerClass() {
    String name1 = "王五";
    // 方法内部类。只能在本方法内使用。无类修饰符。
    class InnerClass3{
      String name = "赵柳";
      public void print(){
        System.out.println("方法name1=" + name1 +",方法内部类name=" + name);
      }			
    }
    InnerClass3 i = new InnerClass3();
    i.print();
  }
  // 外部类使用内部类。
  public static void main(String[] args) {
    // 普通内部类的调用。
    OuterClass o = new OuterClass("张三", 23); // 1. 创建外部类对象。
    InnerClass i = o.new InnerClass(); // 2. 创建内部对象。
    i.show(); // 3. 内部对象调用内部属性和内部方法。
    // 静态内部类的调用。
    InnerClass2 i2 = new InnerClass2(); // 1. 创建内部对象。
    i2.show(); // 2.内部对象调用内部属性和内部方法。
    // 方法内部类的调用。
    OuterClass o2 = new OuterClass(); // 1. 创建外部类对象。
    o2.showInnerClass();
  }
}

2.2 局部内部类——普通局部内部类 + 匿名内部类

2.2.1 普通局部内部类

含义:是方法或作用域中的一个成员。
适用场景:想创建一个类辅助,又不想其是公共可用的。
生命周期:方法和属性中。

(1)方法中

public class OutClass{
  private int num1 = 1;
  private static int num2 = 2;
  private int num5 = 5;
  public void show(){
    int num3 = 3;   //不能加 private
    // 方法中的内部类。
    class InnerClass{  //不能加访问修饰符
      private int num4 = 4;
      private int num1 =  10;
      public void showInner(){
        // 外部类属性
        System.out.println(num1);// 标识符相同时,就近原则。
        
        System.out.println(OutClass.this.num1); // 标识符相同时,调用外部类num1的方法。
        System.out.println(num2);//本来需要OutClass.num2修饰的,但是JDK8不需要。内部类是static class时需要
        System.out.println(num5);//可以直接访问外部类私有变量
        
        // 方法属性。
        System.out.println(num3); 
        
        // 内部类属性。
        System.out.println(num4);         
      }            
  }
  //在方法内,创建内部类实例对象,并调用内部类方法或属性。 
  InnerClass inner = new InnerClass();
  inner.showInner();                                                   
  }
}

(2)作用域中

public class OutClass2{
  public void show(){
    int num = 2;
    if(num == 2){
      class InnerClass{ 
        public void showInner(){
          System.out.println("可以创建作用域中内部类!");      
        }            
      }
      InnerClass inner = new InnerClass();
      inner.showInner();     
    } else{
      System.out.println("不可创建作用域中内部类!");
    }                                                     
  }
}

(3)Test类:

public class Test{
    public static void main(String []args){
        OutClass out = new OutClass();
        out.show();
        OutClass2 out2 = new OutClass2();
        out2.show();
    }
}

2.2.2 匿名内部类——常用

项目含义
含义没有名字的内部类
修饰符
使用场景主要用于不能直接创建对象的抽象类和接口
成员无静态成员,无构造函数。

格式一
类名/接口/抽象类 对象名 = new 类名/接口/抽象类(){
// 匿名内部类类体。
// 属性
// 方法体
};
对象名.方法名();
格式二
new 类名/接口/抽象类(){
// 匿名内部类类体。
}.方法名();

实体类——人类:

public class Person{
  private String name;
  public String getName(){
    return name;
  }
  public Person(){
  }
  public Person(String name){
    this.name = name;
  }
  public void eat(){
    System.out.println("人们");
  }
}

实体类——学生类:

public class Student extends Person{  
  private int clazz;
  public int getClazz(){
    return clazz;
  }
  public Student(){
  }
  public Student(String name, int clazz){
    super(name);
    this.clazz = clazz;
  }
  public void eat(){
    System.out.println("学生");
  }
}

抽象类——动物抽象类:

public abstract class Animal{
    public abstract void bark();
}

实体类——狗类:

public class Dog extends Animal{
    public void bark() {
        System.out.println("汪汪");
    }
} 

接口——运动接口:

public interface Sportable{
    public abstract void sport();
}
2.2.2.1 实体类创建

相当于创建该类的一个子类对象。

public class Test {
  public static void main(String[] args) {
    Student stu=new Student("张三",3);
    System.out.println(stu.getClass()); 
    // 结果:class dayPractice.Student
    
    // 通过实体类创建匿名内部类对象。
    Person p = new Person(){
      public void eat(){
        System.out.println("通过实体类创建匿名内部类对象");
      }
    }; // 分号不能省略。
    p.eat(); // 结果:通过实体类创建匿名内部类对象
    System.out.println(p.getClass()); 
    // 结果:class dayPractice.Test$1    
2.2.2.2 抽象类创建

相当于定义了该抽象类的一个子类对象,并重写了抽象类中所有的抽象方法。

public class Test {
  public static void main(String[] args) {
    Dog dog=new Dog(); // 正常创建实体对象
    dog.bark(); // 结果:汪汪    
    // 通过抽象类创建匿名内部类对象。
    Animal an=new Animal(){
      public void bark(){
        System.out.println("汪汪汪");
      }
    };
    an.bark(); // 结果:汪汪汪
    //返回的是包名加类名
    System.out.println(an.getClass());
    // 结果 class dayPractice.Test$2
2.2.2.3 实体类创建

相当于定义了该接口的一个实现类对象,并重写了接口中所有的抽象方法。

public class Test {
  public static void main(String[] args) {      
   // 通过接口创建匿名内部类对象。
   Sportable s = new Sportable(){
     public void sport(){
       System.out.println("打篮球");
     }
   };
   s.sport();// 结果:打篮球
   System.out.println(s.getClass());
   // 结果:class dayPractice.Test$3  
   
   // 方式二:
   new Sportable(){
     public void sport(){
       System.out.println("打篮球2");
     }
   }.sport();   
   // 结果:打篮球2
 }
}

三、创建内部类

1.3 使用外部类元素
包含:属性,方法,以及使用.this与.new。
特点:可以无限制地访问外围类的元素。

public class OuterClass {
  private String name ;
  private int age;
  public String getName(){
    return name;
  }
  public String getAge(){
    return age;
  }
  public void setName(String name){
    this.name = name;
  }
  public void setAge(String age){
    this.age = age;
  }
  /**
   * 内部类
   * (1)在内部类中:可以直接使用外围类的元素。与修饰符无关。
   * (2)在内部类中:使用直接this调用外部元素。
   */   
  public class InnerClass{
    public InnerClass(){
      name = "张三"; // 直接使用外围类的属性。
      age = 18;
    }        
    public void show(){
      /**
       * 直接使用外围类的属性。如name和getName()效果等价。
       */
      System.out.println("姓名:" + getName() +";年龄:" + getAge());
      System.out.println("姓名2:" + name +";年龄:" + getAge());
    }
    // 同过this,可以直接调用外部类的所用元素。
    public OuterClass getOuterClass(){
      return OuterClass.this; // 返回外部类元素。
    }
  }  
  public void outerShow1(){
    System.out.println("内部类,可以通过.this调用外类所用元素");
  }  
  public static void main(String[] args) {
    /**
     * 主函数中使用内部类。
     * 第一步:创建外部类实例对象。
     * 语法:外类名 外类对象名 = new 外类构造器名();
     * 第二步:通过外部类创建内部类。
     * 语法:外类名.内类名 内类对象名 = 外类对象名.new 内类构造器名();
     * 第三步:调用内部类方法。
     * 语法:内部对象名.内部类方法名。
     */
     // 创建外部类实例对象。
    OuterClass outerClassObject = new OuterClass();
    // 通过外部类调用内部类。
    OuterClass.InnerClass innerClassObject = outerClassObject.new InnerClass();
    /**
     * 调用内部类方法。
     */ 
    innerClassObject.show();
    /**
     * 调用外部类元素
     * 通过在内部类中创建getOuterClass()方法,调用所有外类元素。
     * (1)调用外部类属性
     * (2)调用外部类方法
     */
     // 调用外部类属性
     String strName = innerClassObject.getOuterClass().getName();
     System.out.println(strName); // 张三。
     // 调用外部类方法
     innerClassObject.getOuterClass().outerShow();
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值