内部类速通(java)

public class Main {}//外部其他类
public class Outer //外部类
{
	public class Outer{} //内部类
}

前言:内部类的知识,我感觉是有点难的,细节很多,我的建议是先看多几遍视频再来看一下文章,我相信只要不放弃,看多几次,总能学会,并熟悉的。最后就是看这篇文章可以先跳到总结,再回来看细节

局部内部类

局部内部类一般是在 类中的函数代码块 中 再创建一个类

public class Outer //外部类
{

    //在函数中的内部类
    void func() 
    {
        class Inner 
        {

        }
    }
	
	//在代码块中的内部类
    {
        class Inner2 
        {

        }
    }

}

1.局部内部类,可以访问外部类中所有成员,包括私有

public class Outer {

    private int var1 = 10; //外部类私有变量
    private void f() //外部类私有函数
    {
        System.out.println("hello world!");
    };
    
    void func() //外部类的 func()
    {
        class Inner //内部类
        {
            void print() //内部类的 print
            {
                System.out.println("var1 = " + var1);//内部类访问外部类属性
                f();//内部类访问外部类函数
            }
        }
    }
}


2. 外部类 访问 局部内部类成员:在局部套着内部类的函数创建对象,再访问

public class Main 
{
    public static void main(String[] args) 
    {
        Outer outer = new Outer();
        outer.func();
    }
}
public class Outer 
{

    private int var1 = 10;
    private void f()
    {
        System.out.println("hello world!");
    };

    void func() //外部类的 func()
    {
        class Inner //内部类
        {
            void print() //内部类的 print
            {
                System.out.println("var1 = " + var1);
                f();
            }
        }

        //在套着内部类的这个局部,创建内部类对象,再调用
        Inner inner = new Inner();
        inner.print();
    }
}

在这里插入图片描述

这里在 套着内部类外部类函数 func() 里面创建了内部类的对象,然后调用print函数。然后看到主函数 new 了一个外部类对象外部类对象 调用 了 func()函数 看到下面 new 了一个内部类对象并且调用了内部类的 print 函数


3. 外部其他类 不能 访问局部内部类

public class Outer
{
    private int var1 = 10;
    void func() //外部类的 func()
    {
        class Inner //内部类
        {
            void print() //内部类的函数 print
            {
                System.out.println("var1 = " + var1);
                
            }
        }
    }
}

在这里插入图片描述


4.局部内部类的成员和外部类成员重名,内部类访问外部类成员遵循就近原则,如果想调用外部类的成员,必须用 外部类.this.成员名

public class Main {
    public static void main(String[] args)
    {
        Outer outer = new Outer();
        outer.func();
    }
}
public class Outer
{
    int var1 = 10;//外部类的var1

    void func() //外部类的 func()
    {
        int var1 = 20;//和外部类同名的var1;
        class Inner //内部类
        {
            void print() //内部类的函数 print
            {
                System.out.println("var1 = " + var1);

            }
        }
        
        //调用内部类成员
        Inner inner = new Inner();
        inner.print();
    }
}

在这里插入图片描述

这里可以看到结果是 20,所以同名就遵循就近原则

把 print 中的 var 修改成 outer.this.var1

 System.out.println("var1 = " + Outer.this.var1);

在这里插入图片描述

可以看到输出 var1 是 10,所以同名了想调用外部类的成员,就用 外部类.this.成员名,这个的意思是 外部类对象的引用.成员



匿名内部类

1.基本使用原理

先观察一手代码
基于接口的

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

    void func()
    {
       U u1 = new U()
       {
           @Override
           public void use()
           {
               System.out.println("重写了 U 接口");
           }
       };
       u1.use();
    }
}
interface U {
   public void use();
}

解释

这里可以看到 它 new 了一个 U,但是这个接口是不能 new 的,但是它可以 new, 原理是这样的:
U u1 = new U(){}:底层给了一个看不见的类,然后实现了 U 接口, 然后把这个对象实例化赋给 u1

class 底层给的名 implements U
{
	@Override
	public void use()
    {
    	System.out.println("重写了 use");
    }
}

----

然后把这个类实例化再赋给 u1

基于类的

class U
{
    public void use() {
        System.out.println("原有use");
    }
}

代码把接口 U 改成了类, 其他一样的, U u = new U(){},底层是这样的

class 底层给的名 extends U
{
	@Override
	public void use()
    {
    	System.out.println("重写了 use");
   } 
}

然后把这个类实例化赋给 u


现在我们分析一下 编译类型运行类型

U u1 = new U()

这里 编译类型很明显是 U,然后看运行类型,它其实不是 U,因为我们在上面讲过了它的底层是 创建一个系统命名的类 然后 继承类 或者 实现接口,再实例化对象,赋给左边。所以它实际的运行类型,是 匿名内部类类型


2. 匿名内部类可以,直接访问外部类,所有成员,包括私有

3. 外部其他类 不能访问 匿名内部类

4. 如果外部类和内部类成员重名时,内部类访问的话遵循就近原则,如果想访问外部类成员,可以用 外部类名.this.成员

因为匿名内部类,本身也是在局部的,所以这几点都和局部内部类一样的,这里不再演示了



成员内部类

成员内部类就是类中再弄一个类

class Outer 
{
	class Inner
	{

	}
}

1. 成员内部类可以直接访问外部类,所有成员,包括私有
2.成员内部类和外部类有重名属性或方法,还是用 外部类.this.成员

这几点上面演示过,这里不再演示了


3. 外部类 访问 成员内部类,要创建对象再访问:外部类中弄个方法,方法里创建成员内部类对象,再访问

public class Main {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.useInner();
    }
}
class Outer {//外部类

    private int n1 = 10;
    private void func()
    {
        System.out.println("hello world!");
    };

    class Inner {//成员内部类
        public void say() {
            System.out.println("n1 = " + n1);
            func();
        }
    }

    void useInner(){
        Inner inner = new Inner();
        inner.say();
    }
}

4. 外部其他类 访问 成员内部类

第一种方法

public class Main {//外部其他类
    public static void main(String[] args) {
        Outer o = new Outer();
        Outer.Inner i = o.new Inner();
    }
}

class Outer {
    class Inner{}
}

先要实例化一个外部类对象,然后 Outer.Inner i 的意思就是 Outer 类里的 Inner 类 类型。 o.new Inner():这个我感觉不好理解,只能死记了。


第二种方法

public class Main {//外部其他类
    public static void main(String[] args) {
        Outer o = new Outer();
        Outer.Inner i = o.getInner();
    }
}

class Outer {
    class Inner{}

    public Inner getInner() {
        return new Inner();
    }
}

直接在外部类,写一个方法,返回 Inner 类型的引用,这个感觉好理解一点。



静态内部类

静态内部类,就是成员内部类加了 static

class Outer 
{
	static class Inner
	{

	}
}

1. 静态内部类,可以直接访问,外部类所有静态成员,包括私有,是静态成员,不是所有成员!!!非静态成员不能直接访问
在这里插入图片描述


2. 外部其他类 访问 静态内部类

第一种方法

public class Main {
    public static void main(String[] args) {
        Outer.Inner i = new Outer.Inner();
    }
}

class Outer {
    static class Inner
    {

    }
}

静态的东西 可以直接 通过类名访问,静态的类是的独立的。 所以:Outer.Inner i 就是 Outer 里的 Inner 类 类型,new Outer.Inner(),就是直接 new 一个 Outer 里的 Inner 类。这里讲的还是很抽象,不过没关系,看多就变成常识了。


第二种方法

public class Main {
    public static void main(String[] args) {
       Outer o = new Outer();
       Outer.Inner i =  o.getInner();
    }
}

class Outer {
    static class Inner
    {};

    public static Inner getInner() {
        return new Inner();
    }
}

这个和普通成员内部类一样,通过函数返回对象


3.如果外部类和静态内部类重名,遵循就近原则,不过想访问外部类成员,则可以使用 (外部类名.成员)

public class Main {
    public static void main(String[] args) {
        Outer.Inner i = new Outer.Inner();
        i.print();

    }
}

class Outer {

    static int var = 10;

    static class Inner {
        static int var = 20;
        void print() {
           System.out.println("外部类var: " + Outer.var);
        }
    };
}

在这里插入图片描述



总结

  • 成员内部类 和 静态内部类 本质就是个成员,我觉得可以把 静态内部类 说成 成员静态内部类,这两可以看成一套

  • 局部内部类,匿名内部类 本质是个局部成员,我觉得可以把 匿名内部类 说成 局部匿名内部类,这两可以看成一套

  • 局部的一套 外部其他类 不能 访问局部内部类

  • 成员的一套 外部其他类 可以 访问成员内部类

  • 局部和成员那套:想用外部类访问内部类,必须想办法先实例化对象,再访问

  • 内部类,都可以直接访问外部类成员,包括私有。在外部类和内部类出现重名的时候,访问外部类成员的方式都是 外部类名.this.成员。但是静态内部类不一样,它可以直接外部类名.成员。因为这是静态的特性



一只卑微的大一牛马,水平有限,博客主要用来复习,有错的话,欢迎评论区鞭打我

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值