[java基础] Java中的内部类基础

一、内部类介绍

1.1 什么是内部类

顾名思义,就是定义在另一个类的内部的类

1.2 为什么要使用内部类?

  • 内部类可以对同一个包中的其他类隐藏
  • 内部类方法可以访问定义这个类的作用域中的数据,包括原本私有的数据

二、内部类的划分

  • 成员内部类
  • 静态内部类
  • 方法内部类
  • 匿名内部类

为了更好的理解内部类,我们定义如下两个类,后面的所有说明都基于这两个类:

package com.aran.innerClass;

/**
 * 一个外部类
 *
 * @Author Aran
 * @Date 2020/6/24 8:06 下午
 */
public class Ouuter {
    
}
package com.aran.innerClass;

/**
 * 一个其他类
 * 
 * @Author Aran
 * @Date 2020/6/24 8:06 下午
 */
public class Other {
}

2.1 成员内部类 & 静态内部类

即作为类的成员的内部类,直接写在类的内部的,与类的成员变量和成员方法同级

示例:

package com.aran.innerClass;

/**
 * 一个外部类
 *
 * @Author Aran
 * @Date 2020/6/24 8:06 下午
 */
public class Outter {

    private String  v1= "我是v1,我是Outter的成员变量";

    public void SayHelloInOuuter(){
        System.out.println("Hello,我是Outter的成员方法SayHelloInOutter");
    }

    public class Inner{
        public void SayHiInInner(){
            System.out.println("Hi,我是内部类Inner的SayHiInInner");
        }
    }

}

说明:

  • Outter为Inner的外部类,Inner是Outter的内部类
  • Inner的访问修饰符不受外部类的限制

那么, 这样的内部类是否可以访问外部类的成员变量和方法呢?

示例:

 package com.aran.innerClass;

/**
 * 一个外部类
 *
 * @Author Aran
 * @Date 2020/6/24 8:06 下午
 */
public class Outter {

    private String  v1= "我是v1,我是Outter的成员变量";
    private final String v2 = "我是v2,我是Outter的final变量";
    private static String v3 = "我是v3,我是Outter中的static变量";
    private String v4 = "我是[外部类]的同名非静态变量";
    private static String v5 = "我是[外部类]的同名静态变量";
    public void SayHelloInOuuter(){

        System.out.println("Hello,我是Outter的成员方法SayHelloInOutter,我不是静态的");
    }
    public static void SayHahaInOuuter(){
        System.out.println("Haha,我是Outter的成员方法SayHahaInOuuter,我是静态的");
    }

    public class Inner{
        private String v4 = "我是[内部类]的同名变量";

        /**
         * Inner classes cannot have static declarations
         */
       //private static String v5 = "我是[内部类]的同名静态变量";
        // public static void test();
        public void SayHiInInner(){
            System.out.println("Hi,我是内部类Inner的SayHiInInner");
            System.out.println("内部类访问外部类的普通变量:" + v1);
            System.out.println("++++++++++++++++++++++++++++");
            System.out.println("内部类访问外部类的final变量:" + v2);
            System.out.println("++++++++++++++++++++++++++++");
            System.out.println("下面是内部类访问外部类的非静态&静态方法:");
            SayHelloInOuuter();
            SayHahaInOuuter();
            System.out.println("++++++++++++++++++++++++++++");
            System.out.println("内部类访问外部类的static变量:" + v3);
            System.out.println("++++++++++++++++++++++++++++");
            System.out.println("内部类访问外部类的同名非静态变量:" + Outter.this.v4);
            System.out.println("++++++++++++++++++++++++++++");


        }


    }

    public static class Inner2{
        private static String v5 = "我是[内部类]的同名静态变量";
        private String v4 = "我是[内部类]的同名静态变量";
        public void sayXixiInInner2(){
            System.out.println("静态内部类访问外部类同名静态变量:" + v5);

//            System.out.println("内部类访问外部类的普通变量:" + v1);
//            System.out.println("++++++++++++++++++++++++++++");
//            System.out.println("内部类访问外部类的final变量:" + v2);
//            System.out.println("++++++++++++++++++++++++++++");
//            System.out.println("下面是内部类访问外部类的非静态&静态方法:");
           // SayHelloInOuuter();
            SayHahaInOuuter();
//            System.out.println("++++++++++++++++++++++++++++");
//            System.out.println("内部类访问外部类的static变量:" + v3);
//            System.out.println("++++++++++++++++++++++++++++");
//            System.out.println("内部类访问外部类的同名非静态变量:" + Outter.this.v4);
//            System.out.println("++++++++++++++++++++++++++++");
        }
    }

    public void outterCallInner() {
        Inner inner = new Inner();
        inner.SayHiInInner();

        System.out.println("==============================");
        Inner2 inner2 = new Inner2();
        inner2.sayXixiInInner2();
    }

    public static void main(String[] args) {
        new Outter().outterCallInner();
    }

}

输出:

Hi,我是内部类Inner的SayHiInInner
内部类访问外部类的普通变量:我是v1,我是Outter的成员变量
++++++++++++++++++++++++++++
内部类访问外部类的final变量:我是v2,我是Outter的final变量
++++++++++++++++++++++++++++
下面是内部类访问外部类的非静态&静态方法:
Hello,我是Outter的成员方法SayHelloInOutter,我不是静态的
Haha,我是Outter的成员方法SayHahaInOuuter,我是静态的
++++++++++++++++++++++++++++
内部类访问外部类的static变量:我是v3,我是Outter中的static变量
++++++++++++++++++++++++++++
内部类访问外部类的同名非静态变量:我是[外部类]的同名非静态变量
++++++++++++++++++++++++++++
==============================
静态内部类访问外部类同名静态变量:我是[内部类2]的同名静态变量
Haha,我是Outter的成员方法SayHahaInOuuter,我是静态的

说明:

  • 非静态内部类可以访问外部类的所有信息
  • 在外部类调用内部类,与普通的new对象方法一致
  • 非静态内部类中不能定义静态变量或静态方法
  • 静态内部类不能访问外部类的非静态变量和非静态

如果在Other中该如何Outter内部类的变量和方法呢?

示例:


package com.aran.innerClass;

/**
 * 一个其他类
 *
 * @Author Aran
 * @Date 2020/6/24 8:06 下午
 */
public class Other {

    public static void main(String[] args) {
        Outter outter = new Outter();
        Outter.Inner inner = outter.new Inner();
        //obvious equal to
        /**
         * Outter.Inner inner = new Outter().new Inner();
         */
        inner.SayHiInInner();
    }
}


输出:

Hi,我是内部类Inner的SayHiInInner
内部类访问外部类的普通变量:我是v1,我是Outter的成员变量
++++++++++++++++++++++++++++
内部类访问外部类的final变量:我是v2,我是Outter的final变量
++++++++++++++++++++++++++++
下面是内部类访问外部类的非静态&静态方法:
Hello,我是Outter的成员方法SayHelloInOutter,我不是静态的
Haha,我是Outter的成员方法SayHahaInOuuter,我是静态的
++++++++++++++++++++++++++++
内部类访问外部类的static变量:我是v3,我是Outter中的static变量
++++++++++++++++++++++++++++
内部类访问外部类的同名非静态变量:我是[外部类]的同名非静态变量
++++++++++++++++++++++++++++

可以看出,与直接在Outter中调用结果一致。

说明:

  • 其他类使用内部类的方式: Outter outter = new Outter();
    Outter.Inner inner = outter.new Inner();
    或者:
    Outter.Inner inner = new Outter().new Inner();

2.2 局部内部类

局部,内部类,即,定义在类的成员方法中的类

package com.aran.innerClass;

/**
 * 局部内部类示例
 *
 * @Author Aran
 * @Date 2020/6/25 10:17 上午
 */
public class Outter1 {
    /**
     * 外部类独有属性
     */
    private int v1 = 1;
    /**
     * 外部类同名属性
     */
    private int v2 = 2;
    /**
     * 外部类静态属性
     */
    private static int v3 = 3;
    /**
     * 外部类的非静态方法
     */
    private void OutterMethod(){
        System.out.println("这是外部类的非静态方法!");
    }
    /**
     * 外部类的静态方法
     */
      private static void OutterStaticMethod() {
          System.out.println("这是外部类的静态方法!");
      }

    /**
     * 含有局部内部类的方法
     */
    public void OutterMethodHasInnerClass(){
       int v4 = 4;

        /**
         * 局部内部类,类前不能有访问修饰符
         */
        class Inner{
            private int v5 = 5;
            private final int v2 = 22;

            /**
             * 局部内部类方法
             */
            public void InnerMethod(){
                System.out.println("这是局部内部类的方法!");
                /**
                 * 访问方法内局部变量
                 */
                System.out.println("+++++++++++++++++++++++++++++++++");
                System.out.println("访问局部内部类所在方法内部属性:" + v4);
                /**
                 * 访问外部类同名属性
                 */
                System.out.println("+++++++++++++++++++++++++++++++++");
                System.out.println("外部类的同名属性:" + Outter1.this.v2);
                /**
                 * 外部类的静态属性
                 */
                System.out.println("+++++++++++++++++++++++++++++++++");
                System.out.println("外部类的静态属性:" + v3);
                /**
                 * 访问内部类中的属性
                 */
                System.out.println("+++++++++++++++++++++++++++++++++");
                System.out.println("内部类之内的属性:" + v2);
                /**
                 * Variable 'v4' is accessed from within inner class, needs to be final or effectively final
                 */
                 // v4  = 12;
                /**
                 * 访问外部类中的非静态方法
                 */
                System.out.println("+++++++++++++++++++++++++++++++++");
                System.out.println("访问外部类中的非静态方法");
                OutterMethod();
                /**
                 * 访问外部类中的静态方法
                 */
                System.out.println("+++++++++++++++++++++++++++++++++");
                System.out.println("访问外部类中的静态方法:");
                OutterStaticMethod();
            }
        }


            Inner inner = new Inner();
            inner.InnerMethod();

    }

    public static void main(String[] args) {
        Outter1 outter1 = new Outter1();
        outter1.OutterMethodHasInnerClass();


    }
}

输出:

这是局部内部类的方法!
+++++++++++++++++++++++++++++++++
访问局部内部类所在方法内部属性:4
+++++++++++++++++++++++++++++++++
外部类的同名属性:2
+++++++++++++++++++++++++++++++++
外部类的静态属性:3
+++++++++++++++++++++++++++++++++
内部类之内的属性:22
+++++++++++++++++++++++++++++++++
访问外部类中的非静态方法
这是外部类的非静态方法!
+++++++++++++++++++++++++++++++++
访问外部类中的静态方法:
这是外部类的静态方法!

说明:

  • 局部内部类不能有访问修饰符
  • 除了方法内部,无法调用到内部类
  • 局部内部类不可以有静态方法:
    在这里插入图片描述
  • 可以随意访问外部类中的内容
  • 访问方法内的局部变量时,该变量必须被声明为final的或者事实上是final的,如例子中的v4,也就是说:

    如果想在内部类中使用v4,那么v4不能被修改

3. 匿名内部类

使用局部内部类时,通常还可以再进一步。假如只想创建这个类的一个实例,甚至不需要为类指定名字,这样一个类被称为 匿名内部类

匿名内部类的格式如下:

new SuperType(construction parameters){
	inner class methods and data
}

其中,SuperType可以是接口,如ActionListener,如果是这样,内部类就是实现这个接口。SuperType也可以是一个类,如果是这样,内部类就要扩展这个类。

由于构造器的名字必须与类名相同,而匿名内部类没有类名,所以,匿名内部类不能有构造器。 实际上,构造参数要传递给超类(superclass)构造器。具体地,只要内部类实现一个接口,就不能有任何构造参数。不过,仍是要提供一组小括号:
new InterfaceType()
{
methods and data
}

示例:

package com.aran.innerClass;

/**
 * 接口(interface)中的方法默认都是public的
 * @Author Aran
 * @Date 2020/6/25 6:13 下午
 */
public interface IAnimal {
    void speak();
}


下面实现这个接口



package com.aran.innerClass;

/**
 * @Author Aran
 * @Date 2020/6/25 6:15 下午
 */
public class Outter3 {
    public static IAnimal getInnerInstance(String speak){

        return new IAnimal() {
            @Override
            public void speak() {
                System.out.println(speak);
            }
        };
        //上面的分号必须有
    }

    public static void main(String[] args) {
        /**
         * 调用的speak()是重写后的speak方法
         */
        Outter3.getInnerInstance("小狗 旺旺").speak();
    }
}


输出:

小狗 旺旺

说明:

  • 其中getInnerInstance 中的speak参数必须是final的,或者是事实final的

这一篇是java内部类的基础,不妥之处,望大神指正!

参考

  • csdn
  • 《Java核心技术 卷1》
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值