Java内部类(静态内部类、匿名内部类等)详解

一、什么是内部类

  • 可以将一个类的定义放在另一个类的内部,这就是内部类。我们一般将内部类分为四种:成员内部类静态内部类局部(方法内部类)匿名内部类
  • 外部类的定义是相对于内部类而言的。
    /**
    * 外部类
    */
    public class Outer {
    	//...
    	/**
    	* 内部类
    	*/
    	class Inner {
    		//...
    	}
    }
    

二、内部类

1.成员内部类

总结:【抓住关键字——实例,作为实例成员存在】

  1. 内部类可以是任何的访问修饰符。
    由于成员内部类看起来像是外部类的一个成员,所以可以像类的成员一样拥有多种权限修饰符。
  2. 内部类的内部不能有静态信息。
  3. 内部类也是类,该继承的继承、该重写的重写、该重载的重载,this和super随便用。
  4. 外部类访问内部类的信息,必须先实例化内部类,然后 . 访问。
  5. 内部类可以直接使用外部类的任何信息,如果属性或者方法发生冲突(重名),使用Outer.this.成员
  6. 其他类访问内部类:
    成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在外部类的对象。

其他类访问内部类的方式

public class Test {
    public static void main(String[] args)  {
        //第一种方式:
        Outter outter = new Outter();
        Outter.Inner inner = outter.new Inner();  //必须通过Outter对象来创建
        //第二种方式:
        Outter.Inner inner1 = outter.getInnerInstance();
    }
}
 
class Outter {
    private Inner inner = null;
    public Outter() { 
    }
     
    public Inner getInnerInstance() {
        if(inner == null)
            inner = new Inner();
        return inner;
    }
    /**
    * 成员内部类
    */
    class Inner {
        public Inner() {   
        }
    }
}

2.静态内部类

/**
 * 外部类、内部类定义
 */
public class Outer {

    private int outerVariable = 1;

    /**
     * 外部类定义的属性(重名)
     */
    private static int commonVariable = 2;

    private static int outerStaticVariable = 3;

    static {
        System.out.println("② Outer的静态块被执行了……");
    }

    /**
     * 成员方法
     */
    public void outerMothod() {
        System.out.println("我是外部类的outerMethod方法");
    }

    /**
     * 静态方法
     */
    public static void outerStaticMethod() {
        System.out.println("③ 我是外部类的outerStaticMethod静态方法");
    }

    /**
     * 静态内部类
     */
    public static class Inner {
        /**
         * 成员变量
         */
        private int innerVariable = 10;
        private static int commonVariable = 20;
        private static int innerStaticVariable = 30;

        static {
            System.out.println("① Outer.Inner的静态块执行了……");
        }

        /**
         * 成员方法
         */
        public void innerShow() {
            System.out.println("innerVariable:" + innerVariable);
            System.out.println("外部的commonVariable:" + commonVariable);
            System.out.println("内部的commonVariable:" + Outer.commonVariable);
            outerStaticMethod();
        }

        /**
         * 静态方法
         */
        public static void innerStaticShow() {
            //调用时会先加载Outer类,类加载的时候执行静态代码块
            outerStaticMethod();
            //访问外部类的属性,不重名直接访问
            System.out.println("④ outerStaticVariable" + outerStaticVariable);
        }
    }

    /**
     * 外部类的内部如何和内部类打交道
     */
    public static void callInner() {
        System.out.println(Inner.innerStaticVariable);
        Inner.innerStaticShow();
    }
}

/**
 * 其他类访问静态内部类
 */
class Other {
    public static void main(String[] args) {
        //访问静态内部类的静态方法,Inner类被加载(类加载的时候执行静态代码块),此时外部类未被加载,独立存在,不依赖于外部类。
        Outer.Inner.innerStaticShow();
        //访问静态内部类的成员方法
        Outer.Inner oi = new Outer.Inner();
        oi.innerShow();
    }
}

在这里插入图片描述

总结:【抓住关键字——static,作为静态成员存在】

  1. 静态内部类可以包含任意的信息,可以被任意访问权限修饰符修饰。
  2. 静态内部类的方法只能访问外部类的static关联的成员。
  3. 静态内部类可以独立存在,不依赖于其他外围类。
  4. 其他类访问内部类的静态信息,直接 Outer.Inner.static成员信息 就可以了。
  5. 其他类实例化内部类 Outer.Inner instance = new Outer.Inner();,然后 instance. 成员信息(属性、方法)即可。

3.局部内部类

总结:【抓住关键——作用域,作为方法的局部成员存在】

  1. 局部内部类不能有访问权限修饰符,无法创建静态信息。
    局部内部类就像是方法里面的一个局部变量一样,是不能有访问权限修饰符和static修饰符的。
  2. 只能在方法内部使用。
  3. 可以直接访问方法内的局部变量和参数。【存在限制,需要 final 或有效的final修饰的。】,但是不能更改。
    ①直接被final修饰的变量。
    ②已被赋值且始终未改变的变量(有且仅有赋值一次),引用指向不能改变。JDK8以前(不包括8)只能访问被final修饰的变量。

4.匿名内部类

  • 匿名内部类主要用于在我们需要的时候创建一个对象来执行特定的任务,可以使代码更加简洁。
    • 原本我们需要创建子类或实现类,去继承父类或实现接口,才能重写其中的方法。但是有时候我们这样做了,然而子类和实现类却只使用了一次(定义了一个对象)。这个时候我们就可以使用匿名内部类,不用去写子类和实现类,起到简化代码的作用。
    • 这样做,把子类继承父类,重写父类中的方法,创建子类对象,合成了一步完成,减少了其中创建子类的过程。或者实现类实现接口,重写接口中的方法,创建实现类对象,合成了一步完成,减少了其中创建实现类的过程。
  • 匿名内部类是不能有名字的类,他们不能被引用,只能在创建是用 new 语句来声明他们。
  • 语法格式:
    在这里插入图片描述

匿名类继承父类

public class Anonymous_inner_class {
    public static void main(String[] args) {
        person p = new person(){
            @Override
            public void method() {
                System.out.println("重写父类方法");
            }
        };
        p.method();
    }
}

class person{
    public void method(){
        System.out.println("父类方法");
    }
}

匿名类实现接口

// 自定义的接口
interface Product {
    double getPrice();

    String getName();
}
//外部类
public class Outer {
    public void test(Product p) {
        System.out.println(p.getName() + "-------->" + p.getPrice());
    }

    public static void main(String[] args) {
        Outer as = new Outer();
        //创建匿名内部类,实现接口并实现抽象方法
        as.test(new Product() {
            @Override
            public double getPrice() {
                return 9999.99;
            }

            @Override
            public String getName() {
                return "iPhone 15 pro";
            }
            //这里虽然你增加了自己定义的方法,但是内部类是父类指向子类型的,所以在test方法中也无法调用。
            public Date getDate(){
                return new Date();
            }
        });
    }
}

总结:【匿名内部类通常继承一个类或实现一个接口】

  1. 匿名内部类没有访问权限修饰符。
  2. 匿名内部类要实现父类或接口的所有抽象方法,其他方法可以根据自己的情况进行重写。
  3. 匿名内部类不应当添加自己的成员,因为匿名类没有类名无法向下转型,父类型的引用无法访问。
  4. 匿名内部类访问方法参数时也有和局部内部类同样的限制。
  5. 匿名内部类没有构造方法。
  6. 匿名类是表达式形式定义的,所以末尾以分号;来结束。

三、参考

[1]. 详谈Java内部类(超详细代码示例)
[2] Java 匿名类
[3] Java 内部类详解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小宝945

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

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

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

打赏作者

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

抵扣说明:

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

余额充值