内部类

内部类

一、定义:将一个类A定义在一个类B中,这个类A称之为内部类
二、分类:
成员内部类:将类定义在一个类中的成员位置上,相当于外部类的一个成员
局部内部类:将类定义在一个方法中
三、访问特点:
内部类可以直接访问外部类的成员,包括私有和静态。

class Outer1{
    int a1 = 10;
    private int a2 = 11;
    public static int a3 = 12;
    class Inner1{
        public void fun1(){
//            a1 = 20;
            System.out.println(a1);
//            a2 = 30;
            System.out.println(a2);
//            a3 = 40;
            System.out.println(a3);
        }
    }
}
public class InnerDemo1 {
    public static void main(String[] args) {
        //外部类类名.内部类类名 对象名 = new 外部类类名().new 内部类类名();
        Outer1.Inner1 inner1 = new Outer1().new Inner1();
        inner1.fun1();
    }
}

四、成员内部类的常见修饰符:

private 为了保证数据的安全性
static 为了让数据访问更方便
被静态修饰的成员内部类只能访问外部类的静态成员
内部类被静态修饰后的方法
静态方法
非静态方法

(1)内部类修饰符为静态时
/*
    内部类常用的修饰符:
        static
        private
 */
class Outer2{
    static int a1 = 10;
    private static int a2 = 11;
    public static int a3 = 12;

    static class Inner1{
        public void fun1(){
            System.out.println(a1);
            System.out.println(a2);
            System.out.println(a3);
        }
    }
}
public class InnerDemo2 {
    public static void main(String[] args) {
        Outer2.Inner1 inner1 = new Outer2.Inner1();
        inner1.fun1();
    }
}
(2)当内部类修饰符为私有时
class Outer3 {
    private class Inner {
        public void fun1(){
            System.out.println("好好学习,天天向上!");
        }
    }
    public void show(){
        Inner inner = new Inner();
        inner.fun1();
    }
}
public class InnerDemo2 {
    public static void main(String[] args) {
        Outer3 outer3 = new Outer3();
        outer3.show();
    }
}
结论:通过内部类中写的公共成员show()方法,使外部类的对象来调用,也就间接调用了私有的方法

外部类要访问内部类的成员,必须创建对象。

拓展题(在控制分别输出:30,20,10)

class Outer {
    public int num = 10;
    class Inner {
        public int num = 20;
        public void show() {
            int num = 30;
            System.out.println(num); // 30
            System.out.println(this.num); // 20
            System.out.println(Outer.this.num); // 10
        }
    }
}
public class InnerDemo3 {
    public static void main(String[] args) {
        Outer.Inner inner = new Outer().new Inner();
        inner.show();

    }
}

五、局部内部类

可以直接访问外部类的成员
可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能
局部内部类访问局部变量的注意事项:如果局部内部类中要使用方法中的局部变量的话,这个变量会被使用final关键字进行修饰 final int a = 10;

class Outer4 {

    //成员方法
    public void fun1() {
        //局部变量
        int a = 10; // 如果局部内部类中要使用方法中的局部变量的话,这个变量会被使用final关键字进行修饰
        //局部内部类
        class Inner {
            int b = 20;
            public void show() {
//                a = 11; //  从内部类引用的本地变量必须是最终变量或实际上的最终变量
                b = 12;
                System.out.println(a);
                System.out.println(b);
            }
        }
        Inner inner = new Inner();
        inner.show();
    }
}
public class InnerDemo4 {
    public static void main(String[] args) {
        Outer4 outer4 = new Outer4();
        outer4.fun1();
    }
}

六、为什么必须被final修饰?
因为局部变量会随着方法的调用完毕而消失,这个时候,局部对象并没有立马从堆内存中消失,还要使用那个变量。为了让数据还能继续被使用,就用final修饰,这样,在堆内存里面存储的其实是一个常量值。通过反编译工具可以看一下。

七、匿名内部类

就是内部类的简化写法。
前提:存在一个类或者接口
这里的类可以是具体类也可以是抽象类。
格式:

/*
匿名内部类:
语法定义格式:
new 抽象类/接口(){
//要重写的方法
}
本质:
是一个继承了类或者实现了接口的子类匿名对象

abstract class Demo1{
    public abstract void fun1();
}
//class Demo1Zi1 extends Demo1{
//    @Override
//    public void fun1() {
//        System.out.println("hello world");
//    }
//}
//
//class Demo1Zi2 extends Demo1{
//    @Override
//    public void fun1() {
//        System.out.println("hello");
//    }
//}

class Student1{
    public void show1(Demo1 demo1){
        demo1.fun1();
    }
}

public class NiMingClassDemo1 {
    public static void main(String[] args) {
        Student1 student1 = new Student1();
//        student1.show1(new Demo1Zi());
//        student1.show1(new Demo1Zi2());
        /**
         *  相当于jvm给我们做了几件事情
         *  1、jvm底层自己造了一个类继承抽象类或者实现接口,这个类没有名字
         *  2、重写的方法(实现的方法),我们只需要关注重写的方法
         *  3、将这个类的对象造出来
         */
        student1.show1(new Demo1() {
            @Override
            public void fun1() {
                System.out.println("hello");
            }
        });

        student1.show1(new Demo1() {
            @Override
            public void fun1() {
                System.out.println("hello world");
            }
        });
    }
}
interface Inter1{
    public abstract void fun1();
}
//class Inter1Impl implements Inter1{
//    @Override
//    public void fun1() {
//        System.out.println("hello java");
//    }
//}
class Student2{
    public void show(Inter1 inter1){
        inter1.fun1();
    }
}

public class NiMingClassDemo2 {
    public static void main(String[] args) {
        Student2 student2 = new Student2();
//        student2.show(new Inter1Impl());
        student2.show(new Inter1(){
            @Override
            public void fun1(){
                System.out.println("hello linux");
            }
        });
        student2.show(new Inter1(){
            @Override
            public void fun1(){
                System.out.println("hello java");
            }
        });
    }
}

匿名内部类在开发中的使用

//要求在控制台输出”HelloWorld”
interface Inter {
    void show();
}
//class InterImpl implements Inter{
//    @Override
//    public void show() {
//        System.out.println("HelloWorld");
//    }
//}

class Outer {
    //补齐代码
    public static Inter method(){
        return new Inter() {
            @Override
            public void show() {
                System.out.println("HelloWorld");
            }
        };
    }
}
public class OuterDemo {
    public static void main(String[] args) {
        //我们从调用的方式可以得到一个结论,发现method这个方法是可以被Outer类直接调用的,说明method方法是静态的
        //method方法没有参数
        //调用method方法之后紧跟着可以接着调用show()方法
        //说明method方法调用完后返回的应该是一个对象,而且是一个实现了Inter接口类的对象,method方法的返回值类型是Inter类型
        Outer.method().show();
    }
}
posted @ 2024-08-08 21:59  hello_future  阅读(27)  评论(0)    收藏  举报