JAVA-SE-内部类

目录

一,实例内部类

二,静态内部类

三,局部内部类

四,匿名内部类


内部类就是定义在类里面的类,它又分为:实例内部类,静态内部类,局部内部类和匿名内部类,下面我们来逐个介绍。

一,实例内部类

实例内部类就是未被 static 修饰的类,例如:

class Out{
    public int a;
    private int b;
    private static int c;
    //实例内部类
    class In{
        public int d;
        private int e;
        public void print(){
            System.out.println("内部类!");
        }
    }
    public void show(){
        System.out.println("外部类!");
    }
}

1. 定义了一个实例内部类之后,我们如何去实例化一个实例内部类?

记住一句话:先有外部类对象,再有内部类对象。因为实例内部类是在外部类中定义的,所以实例内部类可以看成是外部类的一个成员,因此在实例化一个实例内部类之前,我们要先实例化一个外部类,而实例化对象的类型是 外部类类名 . 内部类类名 ,例如:

public class Test {
    public static void main(String[] args) {
        //第一种
        Out out = new Out();
        Out.In in = out.new In();
        //第二种
        Out.In in1 = new Out().new In();
    }
}

2. 实例内部类中不能定义一个由 static 修饰的成员,除非是 static final ,这是为什么?

因为由static修饰的成员是类本身的属性,是不依赖于对象的,也就是说由static修饰的成员是在类加载的时候创建的,而不由static修饰的成员因依赖于对象,则是在实例化对象的时候创建,上面提到过实例内部类因定义在外部类中,被当成是外部类中的普通成员,就是说实例内部类(依赖于对象)要在实例化对象的时候创建,而实例内部类中的static修饰的成员(不依赖于对象)则是在类加载时创建,这两者矛盾,所以不能在实例内部类中定义由static修饰的成员。

因为static final 修饰的是一个常量,它不在类加载时创建,而是在编译时完成,所以可以。

3. 在实例内部类方法中访问同名的成员时,我们访问谁的?如果要访问外部类同名的成员,如何访问?

遵守就近原则,优先访问实例内部类的成员,如果要访问外部类同名的成员,用 外部类类名.this.来访问,因为实例内部类的非静态方法中包含了一个指向外部类对象的引用。如下:

class Out{
    public int a = 5;
    private int b;
    private static int c;
    class In{
        public int a = 10;
        public int d;
        private int e;
        static final int f = 10;
        public void print(){
            System.out.println(a);//就近原则,优先访问实例内部类的
            System.out.println(Out.this.a);//要访问外部类同名的成员,用 外部类类名.this.来访问
            System.out.println("内部类!");
        }
    }
    public void show(){
        System.out.println("外部类!");
    }
}

4. 我们如何在外部类方法中访问内部类的成员?

先创建一个实例内部类对象,再通过对象去访问,例如:

class Out{
    public int a = 5;
    class In{
        public int a = 10;
        public int d = 20;
        public void print(){
            System.out.println("内部类!");
        }
    }
    public void show(){
        In in = new In();//只有在外部类中才可以这样实例化
        System.out.println(in.d);
        System.out.println("外部类!");
    }
}

总结一下:

1. 外部类中的任何成员都可以在实例内部类方法中直接访问

2. 实例内部类可以当成外部类的成员,所以实例内部类也受public,private等访问限定符的限制

3. 创建实力内部类对象必须先创建外部类对象

4. 实例内部类不能定义静态成员(除了static final)

5. 在实例内部类方法中访问同名的成员时,优先访问自己的,如果要访问外部类同名的成员,必须使用 外部类类名.this.同名成员 来访问

6. 外部类中不能直接访问内部类中的成员,若要访问,必须先创建实例内部类的对象

二,静态内部类

静态内部类就是被static修饰的类,例如:

class Out{
    public int date1 = 1;
    private static int date2;
    public static void print(){
        System.out.println("外部类!");
    }
    public void print1(){
        System.out.println("1232132");
    }
    //静态内部类
    static class In{
        public int date3 = 3;
        private static int date4 = 4;
        public void test(){
            System.out.println("内部类!");
        }
    }
}

 1. 如何实例化一个静态内部类?

与实例内部类不同,因为静态内部类是由static修饰的,说明静态内部类是外部类本身的属性,因此创建静态内部类时要 new 外部类类名.静态内部类类名();  如下:

public class Test {
    public static void main(String[] args) {
        /*Out.In in1 = new Out().new In();错误写法*/

        Out.In in = new Out.In();//创建静态内部类
    }
}

2. 静态内部类可以定义由static 修饰的成员(即静态成员)

3. 静态内部类的方法不可以直接访问外部类中的非静态成员,为什么?

因为静态内部类是由static修饰,也就是说它不依赖于对象,是在类加载时创建的,而非静态成员依赖于对象,是在实例化对象的时候创建,也就是说,我们在静态内部类中访问的外部类非静态成员时,它们还没有被创建,也就无法访问。

那么我们如何间接的访问呢?很简单,在方法中实例化一个外部类对象,通过对象的引用去访问。

class Out{
    public int date1 = 1;
    private static int date2;
    public static void print(){
        System.out.println("外部类!");
    }
    public void print1(){
        System.out.println("1232132");
    }
    static class In{
        public int date3 = 3;
        private static int date4 = 4;
        public void test(){
            //实例化外部类对象,通过对象访问非静态
            Out out = new Out();
            System.out.println(out.date1);
            out.print1();
            //可以直接访问静态的
            print();
            date2 = 9;
            System.out.println("内部类!");
        }
    }
}

与实例内部类的不同点:

1. 静态内部类对象的创建是直接 new 外部类类名.内部类类名() ,不需要先实例化一个外部类对象

2. 静态内部类中的方法不能直接访问外部类中的静态成员,若硬要访问就必须先实例化一个外部类对象

3. 静态内部类可以定义静态成员

三,局部内部类

局部内部类:定义在外部类方法中的类 - 几乎不使用,了解一下

class Out{
    public void print(){
        class In{
            public int date = 10;
        }
        In in = new In();
        System.out.println(in.date);
    }
}

注意:

1. 局部内部类只能在所定义的方法体内部使用

2. 不能被public、static等修饰符修饰

四,匿名内部类

匿名内部类,顾名思义就是没有名字的类,使用起来与上面的都不同,需要与接口一起使用,代码如下:

interface A{
    void B();
}
public class Test {
    public static void main(String[] args) {
        //可以这样理解:有一个类 实现了A接口 并且重写了 B方法
        //第一种使用方法
        new A(){
            @Override
            public void B() {
                System.out.println("hhhhhh");
            }
        }.B();
        //第二种使用方法
        A a = new A() {
            @Override
            public void B() {
                System.out.println("111111");
            }
        };
        a.B();
    }
}

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一叶祇秋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值