1.内部类分类

1.1 成员内部类

在一个类中除了可以定义成员变量,成员方法,还可以定义类,这样的类叫做成员内部类。

在成员内部类中,可以访问外部类的所有成员,包括成员变量和成员方法,在外部类中,同样可以访问成员内部类的变量和方法。(与访问的控制符有关,即private,public,protracted,default)

class Outer{
    private int m=0;

    public void show1(){
        System.out.println("外部类");
    }
    class Inner{
        private int mm=0;
        public void show2(){
            System.out.println("内部类");
        }
    }
    public void test3(){
        Inner inner = new Inner();
        inner.show2();
    }
}
public class test {
    public static void main(String[] args) {
        //调用方式1
        Outer outer = new Outer();
        outer.show1();
        outer.test3();
        System.out.println();
        //调用方式2
        Outer.Inner io = new Outer().new Inner();
        io.show2();
        System.out.println();
        //调用方式3
        Outer.Inner io2 = outer.new Inner();
        io2.show2();
    }
}

alt

1.2 局部内部类

局部内部类,也叫方法内部类,就是定义在某个局部范围中的类,它和局部变量一样,都在方法中定义,其有效范围只限于方法内部。

在局部内部类中,局部内部类可以访问外部类的所有成员方法成员变量,而局部内部类中的变量和方法却只能在创建该局部内部类的方法中进行访问。

class Outer{
    private int m=0;

    public void show1(){
        System.out.println("外部类");
    }
    public void test2(){
        //定义局部内部类
        class Inner{
            private int mm=0;
            public void show2(){
                System.out.println("内部类");
            }
        }
        Inner inner = new Inner();
        inner.show2();
    }
}
public class test {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.show1();
        outer.test2();
    }
}

alt

1.3 静态内部类

静态内部类,就是使用static关键字修饰的成员内部类,与成员内部类相比。在形式上,静态内部类只是在内部类前增加了static关键字,但是在功能上,静态内部类中只能访问外部类中的静态成员,同时通过外部类访问静态内部类成员时,可以跳过外部类从而直接通过内部类访问静态内部类成员。

class Outer{
    static int m=0;
    public static class Inner{
        public void show(){
            System.out.println("静态内部类");
        }
    }
}
public class test {
    public static void main(String[] args) {
        Outer.Inner io = new Outer.Inner();
        io.show();
    }
}

alt

1.4 匿名内部类

在Java中调用某个方法时,如果该方法的参数是一个接口类型,除了可以传入一个参数接口实现类,还可以使用匿名内部类实现接口来作为该方法的参数。匿名内部类其实就是没有名称的内部类,在调用包含有接口类型参数的方法时,通常为了简化代码,不会创建一个接口的实现类作为方法参数传入,来是直接通过匿名内部类的形式传入一个接口类型参数,在匿名内部类中直接完成方法的实现。

创建匿名内部类的格式:

new 父接口(){
	//匿名内部类实现部分
}
interface Animal{
    public void shout();
}
public class test {
    public static void main(String[] args) {
        String name="黑豆";
        animalShout(new Animal() {
            @Override
            public void shout() {
                System.out.println(name+"汪汪汪...");
            }
        }
        );
    }

    private static void animalShout(Animal animal) {
        animal.shout();
    }
}

alt

(1)在创建animalShout()方法时,在方法的参数位置写上new Animal(){},这相当于创建了实例对象,并将对象作为参数传给animalShout()方法。在new Animal()后面有一对大括弧,表示创建的对象为Animal的子类实例,该子类是匿名的。代码如下:

animalShout(new Animal(){});

(2)在大括号中编写匿名子类的实现代码,如下所示:

animalShout(new Animal() {
            @Override
            public void shout() {
                System.out.println(name+"汪汪汪...");
            }
        }
        );

2.内部类的作用

(1)内部类可以很好的实现隐藏。

非内部类是不可以使用 private和 protected修饰的,但是内部类却可以,从而达到隐藏的作用。同时也可以将一定逻辑关系的类组织在一起,增强可读性。

(2)间接的实现多继承。

每个内部类都能独立地继承自一个(接口的)实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。所以说内部类间接的实现了多继承。

class Father {
    public int strong() {
        // 强壮指数
        return 9;
    }
}

class Mother {
    public int kind() {
        // 友好指数
        return 8;
    }
}
class Son {
    // 内部类继承Father类
    class Father_1 extends Father {
        public int strong() {
            return super.strong() + 1;
        }
    }
    class Mother_1 extends Mother {
        public int kind() {
            return super.kind() - 2;
        }
    }
    public int getStrong() {
        return new Father_1().strong();
    }
    public int getKind() {
        return new Mother_1().kind();
    }
}

public class test {
    public static void main(String[] args) {
        Son son = new Son();
        System.out.println("Son 的强壮指数:" + son.getStrong());
        System.out.println("Son 的友好指数:" + son.getKind());
    }
}

alt