跳至主要內容

Java

LincZero大约 6 分钟

Java

目录

内部类(这章不看书了,看视频学)

简概

概念

  • 概念

    • 什么是内部类?内部类就是在类里面再定义一个类
  • 使用场景

    • 内部类表示的事物是外部类的一部分
    • 内部类单独出现没有任何意义
  • 访问权限

    • 内部类可以访问外部类包括私有在内的所有成员
    • 外部类要访问内部类成员时必须创建对象
  • 使用场景举例

    • 例如:汽车的发动机、ArrayList的迭代器、人的心脏

    • 汽车的发动机

      /*
       * - 需求:写一个Javabean类描述汽车
       * - 属性:品牌、车龄、颜色、发动机品牌、使用年限
       */
      public class Car {
          String carName;
          int carAge;
          int carColor;
          
          public class Engine { // 需要依赖车,不会单独定义
          	String engineName;
              int engineAge;
          }
      }
      
    • 核心类库ArrayList

      IDEA > Ctrl+N > 输入ArrayList > 选择ArrayList.java.util

      文件中Ctrl+F10 > 会出现很多类内内容,红色m是方法、黄色f是字段/属性、蓝色C是内部类

      然后可以看到里面有四个内部类,现在我们看内部类 Itr

归纳总结一下

类的五大成员:属性、方法、构造方法、代码块、内部类

类的相对位置可分:外部类、内部类、外部其他类

内部类的分类:

  • 成员内部类(不需要自己写,能看懂就行)
  • 静态内部类(不需要自己写,能看懂就行)
  • 局部内部类(不需要自己写,能看懂就行)
  • 匿名内部类**(实际开发用得最多)**

成员内部类

简概

  • 概念
    • 写在成员位置的,属于外部类的成员
  • 注意
    • 成员内部类可以被一些修饰符所修饰,比如:private、默认、protected、public、static等
    • 我们一般说 “成员内部类” ,不指用static修饰的情况,那叫 “静态内部类”
    • JDK16之前不能在成员内部类里面定义静态变量

定义内部类

public class Car {	// 外部类
	string carName;
    int carAge;
    int carcolor;
    class Engine {  // 成员内部类
        string engineName;
        int engineAge;
    }
}

外界调取

  • 方式一:在外部类中编写方法,对外提供内部类的对象

  • 方式二:直接创建格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象

    public class Outer {
        String name;
        /*private*/ class Inner {
            static int a = 10;					// 注意:JDK16之前不能在成员内部类里面定义静态变量
        }
        public Inner getInstance(){
            return new Inner();
        }
    }
    
    // 创建内部类的方式 2
    System.out.println(new Outer().name);		// 获取普通成员
    Outer.Inner oi = new Outer().new Inner();   // 获取内部类。如果内部类是private则不能用该写法
    
    // 创建内部类的方式 1
    Outer o = new Outer();
    Object inner = o.getInstance();
    System.out.println(o.getInstance());		// 或
    

    例如核心内库中的ArrayList

    public Interator<E> iterator() {			// 该方法返回ArrayList类里的迭代器(内部类)
        return new Itr();
    }
    
    private class Itr implement Interator<E> {...}
    

成员内部类获取外部类、原理

public class Outer {
    private int a = 10;
    
    class Inner {
        private int a = 20;
        
        public void show() {
        	int a = 30;
            system.out.println(a); 				// 30
            system.out.print1n(this.a);			// 20
            system.out.print1n(Outer.this.a);	// 10
        }
    }
}

原理(内存图)

image-20220820140516600
image-20220820140516600

静态内部类

简概

静态内部类只能访问外部类中的静态变量和静态方法,如果想要访问非静态的需要创建对象。

定义内部类

public class Car{			// 外部类
    String carName;
    int carAge;
    int carColor;
    static class Engine{	// 静态内部类
        String engineName;
        int engineAge;
    }
}

// 创建静态内部类
外部类名.内部类名 对象名 = new 外部类名.内部类名();
// 调用非静态方法的格式
先创建对象再用对象调用
// 调用静态方法的格式
外部类名.内部类名.方法名();

外界调取

  • 注意事项

    • 静态内部类也是成员内部类中的一种

    • 静态内部类只能访问外部类的静态变量和静态方法,如果想要访问非静态的需要创建外部类的对象

先复习一下 静态成员变量

public class Outer {
	int a = 10;				// 非静态成员变量
    static int b = 20;		//  静态成员变量
    
    // 静态内部类
    static class Inner {
        public void show1(){			// 非静态方法
            Outer o = new Outer();
            system.out.print1n(o.a);	// 非静态成员变量
            system.out.print1n(b);		//  静态成员变量
        }
        public static void show2(){		//  静态方法
            Outer o = new Outer();
            system.out.print1n(a) ;		// 非静态成员变量
            system.out.println(b);		//  静态成员变量
        }
    }
}

调用 静态内部类

public class Outer {
    // 静态内部类
    static class Inner {
        public void show1(){
            System.out.println("静态内部类里的 非静态方法")
        }
        public static void show2(){
            System.out.println("静态内部类里的  静态方法")
        }
    }
}

public class Test{
    public static void main(String[] args) {
        Outer.Inner oi = new Outer.Inner();		// 静态内部类
        oi.show1();								// 静态内部类里的 非静态方法
        // oi.show2();							// 			(强行写也行)
        Outer.Inner.show2();					// 静态内部类里的  静态方法
    }
}

局部内部类

简概

概念:将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量。

没什么用

定义内部类

public class Outer{
    public void show(){
        int a = 10;
        // 局部内部类。和局部变量是类似的,可以使用一些final static等的修饰符
        class Inner{
            
        }
    }
}

外界调取

该局部内部类只能在局部里使用,外界用不了

访问权限

  • 外界是无法直接使用,需要在方法内部创建对象并使用。
  • 该类可以直接访问外部类的成员,也可以访问方法内的局部变量。

匿名内部类【重要】

简概

  • 概念

    • 匿名内部类的本质是隐藏了名字的内部类
  • 结构 匿名内部类包含三部分,更准确得说应该叫 “匿名内部类的对象”

    • 继承或实现

    • 方法重写

    • 创建对象

  • 补充 可以些在成员位置,也可以写在局部位置。

定义内部类

格式

// 格式
new 类名或接口名() {
	重写方法;
}

// 例如
new Inter() {
    public void show() {
        
    }
}

代码与原理

public class Test {
    public static void main(String[] args){
        // 编写匿名内部类的代码
        new Swim() {
            @Override
            public void swim(){
                System.out.println("重写的游泳方法")
            }
        }
    }
}

// 分析
// 1. 下面的Student类实现Swim接口了
// 2. 大括号前面的内容删掉,换成Swim,便成了一个匿名内部类
// 3. Swim的前面加关键字new、后面加括号,表示创建这个类的对象
        public class Student implements Swim {	// 你会发现大括号里的内容和匿名内部类是一样的
            @Override
            public void swim(){
                System.out.println("重写的游泳方法")
            }
        }

应用举例、原理、应用场景

public class Test {
    public static void main( String[] args) {
        
        // 编写匿名内部类的代码
        // 编译时其实会生成相关字节码:Test$1.class(可以在工程文件的out文件里找),这个名字是自动生成的。
        // 可以用javap反编译这个字节码,会发现这个文件的内容就是这个匿名类的内容
        new swim(){
            @override
            public void swim(){ system.out.println("重写了swim方法"); }
        };
        
        // 应用场景:如果这个类只要用一次,就可以不去重新定义一个类,简化代码
        // 然后比如这个类就可以传给接受Animal引用的函数
        new Animal(){
            @override
            public void eat() { system.out.println("重写了eat方法"); }
        };
    }
}