Java 内部类

内部类

  · 内部类可以是静态static的,也可用public,default,protected和private修饰

  · 内部类是一个编译时的概念,一旦编译成功就会成为完全不同的两类。如下编译完成后出现Computer.class和Computer$CPU.class两类。
     所以内部类的成员变量或方法名可以和外部类的相同。

使用内部类的好处:

  · 解决多重继承的问题,当一个类需要实现两个父类,可以使用内部类实现其中一个类。

  · 使用内部类可以非常方便的编写事件驱动程序,可用内部类实现接口方法

  · 如果某个类与实现的接口中拥有同名同参的函数,可用内部类实现接口,这样外部类和内部类同时存在相同名称和参数列表的函数

1. 成员内部类

  · 成员内部类不能含有static的变量和方法。因为成员内部类需要先创建了外部类,才能创建它自己的

  · 成员内部类要引用外部类对象时,使用Computer.this来表示外部类对象。外部类要访问内部类的所有成员变量/方法,则需要通过内部类的对象来获取new CPU().timeout

class Computer {
    private int timeout = 100;
    
    public void work(int timeout) {
        new CPU().process(timeout);
    }
    
    public CPU getCPU() {
        return new CPU();
    }
    
    public class CPU {
        public int timeout = 200;
        
        public void process(int timeout) {
            System.out.println("局部变量: " + timeout);
            if(timeout == 300){
                System.out.println("内部类变量: " + this.timeout);
                System.out.println("外部类变量: " + Computer.this.timeout);
            }
        }
    }

}

public class Test {
    public static void main(String[] args) {
        Computer cp = new Computer();
        System.out.println("a. 使用外部类对象cp 直接调用外部类方法");
        cp.work(300);
        
        System.out.println("b. cp.new 获取内部类对象,并调用内部类方法 ");
        Computer.CPU cpu1 = cp.new CPU();    // 如果CPU类是private的, 那么该语句会发生错误,在Computer外部无法获取到内部类CPU,只能在Computer中操作CPU类
        cpu1.process(400);
        
        System.out.println("c. cp.getCPU()获取内部类对象,并调用内部类方法 ");
        Computer.CPU cpu2 = cp.getCPU();    
        cpu2.process(500);
    }
}

运行结果

a. 使用外部类对象cp 直接调用外部类方法
  局部变量: 300
  内部类变量: 200
  外部类变量: 100
b. cp.new 获取内部类对象,并调用内部类方法
  局部变量: 400
c. cp.getCPU()获取内部类对象,并调用内部类方法
  局部变量: 500

2. 局部内部类

  局部内部类,是指内部类定义在方法和作用域内。局部内部类也像别的类一样进行编译,但只是作用域不同而已,只在该方法或条件的作用域内才能使用,退出这些作用域后无法引用的。

class Computer {
    
    public void work(boolean flag) {
        
        class IntelCPU implements CPU{
            public void process() {
                System.out.println("内部类IntelCPU 定义在方法内");
            }
        }
        new IntelCPU().process();
        
        if(flag){
            class AMDCPU implements CPU{
                public void process() {
                    System.out.println("内部类AMDCPU 定义在作用域内");
                }
            }
            new AMDCPU().process();
        }
    }
}

interface CPU{
    public void process();
}

public class Test {
    public static void main(String[] args) {
        Computer cp = new Computer();
        cp.work(true);
    }
}

运行结果

    内部类IntelCPU 定义在方法内
    内部类AMDCPU 定义在作用域内

3. 匿名内部类
class Computer {
    
    public CPU getCPU() {
        return new CPU(){
            public void process() {
                System.out.println("匿名内部类");
            }
        };
    }
}

abstract class CPU{
    public abstract void process();
}

public class Test {
    public static void main(String[] args) {
        Computer cp = new Computer();
        cp.getCPU().process();
    }
}

 

匿名内部类,局部内部类的方法和作用域中使用的外部变量必须是 final 的,因为内部类会自动拷贝外部变量的引用,用 final修饰该引用可避免:
  a) 外部方法修改引用,而导致内部类得到的引用值不一致
  b) 内部类修改引用,而导致外部方法的参数值在修改前和修改后不一致。

class Computer {

    public CPU getCPU(final int timeout, int type) {  // timeout变量在匿名内部类中使用,应设为final类型
        
        return new CPU(timeout, type) {
            private int timeout_ = timeout;  // 匿名内部类的成员变量不能和外部传递的参数名一样
            public int getTimeOut() {
                return timeout_;
            }
        };
    }
}

abstract class CPU {
    CPU(int timeout, int type) {
    }
    public abstract int getTimeOut();
}

public class Test {
    public static void main(String[] args) {
        Computer cp = new Computer();
        CPU cpu = cp.getCPU(100, 1);
        System.out.println(cpu.getTimeOut());
    }
}

 
4. 嵌套内部类
    · 嵌套内部类就是修饰为static的内部类,不需要内部类对象和外部类对象之间的联系。我们可以直接引用Computer.CPU,即不需要创建外部类,也不需要创建内部类。
    · 普通内部类不能有static数据和static属性,也不能包含嵌套类,但嵌套类可以。而嵌套类不能声明为private,一般声明为public。
class Computer {
    
    public static class CPU{
        public void process() {
            System.out.println("嵌套内部类");
        }
    }
}

public class Test {
    public static void main(String[] args) {
        Computer.CPU cpu = new Computer.CPU();
        cpu.process();
    }
}
原文地址:https://www.cnblogs.com/anxiao/p/6739794.html