JavaSE笔记6.13-面向对象-内部类

一. 概述

1. 定义

将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类、嵌套类)。
当描述事物时,事物的内部还有事物,该事物用内部类来描述。

2. 访问规则(互访)
(1)内部类可以直接访问外部类中的成员(包括私有)

之所以可以直接访问外部类中的成员,是因为内部类中持有一个外部类的引用。
该引用的写法是:外部类名.this

(2)外部类要访问内部类,必须建立内部类的对象
class Outer
{
	private int x=3;

	//内部类
	class Inner  
	{
		void function()
		{
			//内部类访问外部类
			//无需创建对象就可访问Outer类中的成员变量与成员函数
			System.out.println("Inner:"+x);
		}
	}

	void method()
	{
		//外部类访问内部类
		//必须先建立内部类的对象
		Inner in=new Inner();
		in.function();
	}
}


class  InnerClassDemo
{
	public static void main(String[] args) 
	{
		Outer out=new Outer();
		out.method();
	}
}

输出结果是:
Inner:3

class Outer
{
    private int x=3;

    //内部类
    class Inner
    {
        void function()
        {
            //内部类访问外部类
            //无需创建对象就可访问Outer类中的成员变量与成员函数
            System.out.println("Inner:"+x);
        }
    }
}


class  InnerClassDemo
{
    public static void main(String[] args)
    {
        //访问内部类中的成员
        Outer.Inner in=new Outer().new Inner();
        in.function();
    }
}

输出结果是:
Inner:3

3. 内部类可以直接引用外部类中成员的原理
(1)打印内部类中的局部变量
class Outer
{
    private int x=3;

    //内部类
    class Inner
    {
        int x=4;
        void function()
        {
            int x=6;
            System.out.println("Inner:"+x);
        }
    }
    void method()
    {
        Inner in=new Inner();
        in.function();
    }
}


class  InnerClassDemo
{
    public static void main(String[] args)
    {
        Outer out=new Outer();
        out.method();
    }
}

输出结果是:
Inner:6

(2)打印内部类中的成员变量
class Outer
{
    private int x=3;

    //内部类
    class Inner
    {
        int x=4;
        void function()
        {
            int x=6;
            System.out.println("Inner:"+this.x);
        }
    }
    void method()
    {
        Inner in=new Inner();
        in.function();
    }
}


class  InnerClassDemo
{
    public static void main(String[] args)
    {
        Outer out=new Outer();
        out.method();
    }
}

输出结果是:
Inner:4

(3)打印外部类中的成员函数
class Outer
{
    private int x=3;

    //内部类
    class Inner
    {
        int x=4;
        void function()
        {
            int x=6;
            System.out.println("Inner:"+Outer.this.x);
        }
    }
    void method()
    {
        Inner in=new Inner();
        in.function();
    }
}


class  InnerClassDemo
{
    public static void main(String[] args)
    {
        Outer out=new Outer();
        out.method();
    }
}

输出结果是:
Inner:3

4. 访问格式

(1)当内部类定义在外部类的成员位置上,而且非私有,在外部其他类中可以直接建立内部类对象

格式:
外部类名.内部类名 变量名=外部类对象.内部类对象
例:
Outer.Inner in=new Outer().new Inner();

(2)当内部类在成员位置上,就可以被成员修饰符所修饰

比如:
private:将内部类在外部类中进行封装
static:内部类就具备了静态特性。

二. 静态内部类

1. 静态内部类只能直接访问外部类中的静态成员

出现了访问局限
在这里插入图片描述

2. 在外部其他类中,如何直接访问静态内部类呢?
(1)访问静态内部类的非静态成员

new Outer.Inner().function();

class Outer
{
    //用static修饰,才可以被静态内部类Inner访问
    private static int x=3;

    //静态内部类
    static class Inner
    {
        void function()
        {
            System.out.println("Inner:"+x);
        }
    }
}

class  InnerClassDemo
{
    public static void main(String[] args)
    {
		/*
		1. 内部类Inner是静态的,可以直接被类名调用
		2.function是非静态的,需要由对象来调用
		外部类名.内部类对象.内部类中的非静态函数
		*/
        new Outer.Inner().function();
    }
}

输出结果为:
Inner:3

(2)访问静态内部类的静态成员

outer.Inner.function();

class Outer
{
    //用static修饰,才可以被静态内部类Inner访问
    private static int x=3;

    //静态内部类
    static class Inner
    {
        static void function()
        {
            System.out.println("Inner:"+x);
        }
    }
}

class  InnerClassDemo
{
    public static void main(String[] args)
    {
		/*
		1. 内部类Inner是静态的,可以直接被类名调用
		2.function是静态的,可以直接被类名调用
		外部类名.内部类名.内部类中的静态函数
		*/
        Outer.Inner.function();
    }
}

输出结果为:
Inner:3

3. 注意

(1)当内部类中定义了静态成员,该类必须是静态的
(2)当外部类中的静态方法访问内部类时,内部类也必须是静态的

三. 内部类的位置

1. 内部类定义在成员位置上

(1)可以被private、static成员修饰符修饰
(2)被static修饰的内部类只能访问外部类中的静态成员
(3)当内部类定义了静态成员,该类必须是静态的

2. 内部类定义在局部位置上

(1)可以直接访问外部类中的成员,因为还持有外部类中的引用

class Outer
{
    int x=3;
    void method()
    {
        class Inner
        {
            void function()//可直接访问外部类中的成员
            {
                System.out.println(x);
            }
        }
		/*
        当调用method方法时,function方法不直接运行
		需要先创建对象,由对象来运行function方法
		*/
        new Inner().function();
    }
}

class InnerClassDemo3
{
    public static void main(String[] args)
    {
        new Outer().method();
    }
}

(2)不可以被成员修饰符private、static修饰
内部类中的成员变量和成员函数也不能被static修饰,因为一旦被static修饰,该内部类也必须是静态的
(3)可以访问它所在的局部中的局部变量,但必须是被final修饰的
在这里插入图片描述

为什么局部内部类和匿名内部类只能访问final的局部变量?
追究其根本原因就是作用域中变量的生命周期导致的:

  1. 内部类和外部类是处于同一个级别的,内部类不会因为定义在方法中就会随着方法的执行完毕就被销毁
  2. 当外部类的方法结束时,局部变量就会被销毁了,但是内部类对象可能还存在(内部类对象访问了一个不存在的变量)
  3. 为了以上问题,就将局部变量复制了一份作为内部类的成员变量
  4. 将局部变量复制为内部类的成员变量时,必须保证这两个变量是一样的;通过将局部变量设置为final来解决

四. 匿名内部类

1. 引入

匿名内部类就是内部类的简写格式

2. 定义匿名内部类的前提

内部类必须继承一个类或者实现接口(继承的是外部其他类)
在这里插入图片描述

3. 格式
new 父类或者接口(可传值)
{
    定义子类的内容
}
(1)非匿名内部类形式
abstract class AbsDemo
{
	abstract void show();
}

class Outer
{
	int x=3;
	class Inner extends AbsDemo //内部类可以继承外部其他类
	{
		void show()
		{
			System.out.println("show:"+x);
		}
	}
	public void function()
	{
		new Inner().show();
	}
}


class InnerClassDemo4 
{
	public static void main(String[] args) 
	{
		new Outer().function();
	}
}
(2)匿名内部类形式
abstract class AbsDemo
{
    abstract void show();
}

class Outer
{
    int x=3;
    public void function()
    {
        new AbsDemo(){
            void show()
            {
                System.out.println("show:"+x);
            }
        }.show();
    }
}

class InnerClassDemo4
{
    public static void main(String[] args)
    {
        new Outer().function();
    }
}
4. 实质

匿名内部类就是一个匿名子类对象
而且这个对象有点胖,可以理解为带内容的对象

5. 匿名类中可以定义匿名子类特有的方法
abstract class AbsDemo
{
    abstract void show();
}

class Outer
{
    int x=3;
    public void function()
    {
        new AbsDemo(){
            void show()
            {
                System.out.println("show:"+x);
            }
            void abc()
            {
                System.out.println("haha");
            }
        }.abc();
    }
}

class InnerClassDemo4
{
    public static void main(String[] args)
    {
        new Outer().function();
    }
}
6. 给匿名内部类起名字(存在局限不实用)

(1)调用匿名内部类中不同方法,需要创建多个匿名子类对象;为了解决以上麻烦,可以给匿名内部类起名(实际上是多态)
(2)实际上只能调用父类/接口中的函数,不能调用匿名子类中特有的函数(具有局限性不实用)
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值